Java中的Thread
类是多线程编程的核心组件。
1. 什么是线程?
- 线程(Thread) 是程序执行的最小单位。一个Java程序默认至少有一个主线程,即
main
线程,负责执行main()
方法。 - 一个进程(Process) 可以包含多个线程,多个线程可以共享进程中的资源(如内存、文件句柄等)。
- Java使用
Thread
类和Runnable
接口来实现多线程编程。
2. 创建线程的三种方式
Java中创建线程主要有以下三种方式,每种方式有其适用场景。
方式一:继承 Thread 类
通过继承Thread
类并重写run()
方法实现线程逻辑。创建线程对象后,调用start()
方法启动线程。
特点:
- 不适合需要继承其他类的场景(Java单继承限制)。
- 更直接,适合简单的线程任务。
示例:
class MyThread extends Thread {
@Override
public void run() {
// 线程执行的任务
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
}
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.start(); // 启动线程
thread2.start();
}
}
输出示例(结果不固定):
Thread-0 - 0
Thread-1 - 0
Thread-0 - 1
Thread-1 - 1
...
方式二:实现 Runnable 接口
通过实现Runnable
接口,并将实现类的对象传递给Thread
构造函数。
特点:
- 更灵活,适合需要继承其他类的场景。
- 解耦线程逻辑与线程控制。
示例:
class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的任务
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
}
}
}
public class RunnableExample {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
}
}
方式三:使用 Lambda 表达式(推荐方式)
Java 8 引入了 Lambda 表达式,可以更简洁地定义线程任务。
特点:
- 简化代码,适合轻量级的线程任务。
- 适用于实现
Runnable
接口的方式。
示例:
public class LambdaExample {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
}
});
thread1.start();
thread2.start();
}
}
3. Thread
类的重要方法
Java中的Thread
类提供了丰富的方法,用于控制线程的执行行为。
(1) 启动线程
start()
:启动线程并调用其run()
方法,开启线程的新执行路径。
thread.start();
注意: 不能直接调用run()
,否则线程不会真正启动。
(2) 获取/设置线程名称
getName()
:获取线程名称。setName(String name)
:设置线程名称。
示例:
Thread thread = new Thread(() -> {
System.out.println("线程名称:" + Thread.currentThread().getName());
});
thread.setName("MyThread");
thread.start();
(3) 线程休眠
Thread.sleep(long millis)
:让当前线程暂停执行,进入休眠状态。
- 单位为毫秒。
- 休眠过程中线程不会释放锁。
示例:
try {
System.out.println("线程休眠...");
Thread.sleep(2000); // 休眠2秒
System.out.println("休眠结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
(4) 线程合并
join()
:等待一个线程执行完成。
示例:
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
}
});
thread.start();
try {
thread.join(); // 等待线程执行完成
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程已完成");
(5) 中断线程
interrupt()
:中断线程(通知线程停止)。isInterrupted()
:检查线程是否被中断。
示例:
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程正在运行...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// 捕获中断异常并退出循环
System.out.println("线程被中断");
break;
}
}
});
thread.start();
try {
Thread.sleep(2000); // 主线程休眠2秒
thread.interrupt(); // 中断子线程
} catch (InterruptedException e) {
e.printStackTrace();
}
(6) 检查线程状态
isAlive()
:检查线程是否仍在运行。getState()
:获取线程的当前状态。
4. 线程的生命周期
线程的生命周期包括以下五种状态:
- 新建(NEW): 线程对象被创建,但未调用
start()
方法。 - 就绪(RUNNABLE): 线程调用
start()
方法,等待CPU调度。 - 运行(RUNNING): 线程被CPU调度并执行任务。
- 阻塞(BLOCKED/WAITING): 线程因某些操作(如锁、等待)暂停。
- 终止(TERMINATED): 线程执行完毕或被中断。
- 也称新生、就绪、运行、阻塞、死亡
示例:
Thread thread = new Thread(() -> {});
System.out.println(thread.getState()); // NEW
thread.start();
System.out.println(thread.getState()); // RUNNABLE
5. 多线程中的问题及解决方法
(1) 线程安全问题
多个线程访问共享资源可能导致数据不一致。
解决方法:使用同步机制(synchronized)。
示例:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class SynchronizedExample {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("最终计数:" + counter.getCount());
}
}
(2) 死锁问题
多个线程因资源争用互相等待,导致无法继续执行。
示例:
class DeadlockExample {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
System.out.println(Thread.currentThread().getName() + " 获得锁1");
synchronized (lock2) {
System.out.println(Thread.currentThread().getName() + " 获得锁2");
}
}
}
public void method2() {
synchronized (lock2) {
System.out.println(Thread.currentThread().getName() + " 获得锁2");
synchronized (lock1) {
System.out.println(Thread.currentThread().getName() + " 获得锁1");
}
}
}
}
public class DeadlockDemo {
public static void main(String[] args) {
DeadlockExample example = new DeadlockExample();
Thread t1 = new Thread(example::method1);
Thread t2 = new Thread(example::method2);
t1.start();
t2.start();
}
}
解决方案:
- 避免嵌套锁。
- 使用锁的超时机制(如
tryLock
)。 - 通过锁排序避免循环等待。
6. 高级线程工具
Java 提供了更高级的并发工具(java.util.concurrent
包):
ExecutorService
:线程池管理。CountDownLatch
:线程等待计数器。Semaphore
:限制线程并发数。Future
:获取线程任务结果。
线程池示例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " 正在执行任务");
});
}
executor.shutdown();
}
}
评论留言
欢迎您,!您可以在这里畅言您的的观点与见解!
0 条评论