1. 线程状态转换图
新建(New)
初始状态,线程被构建,但是还没做调用start()
方法。
可运行(Runnable)
可能正在运行,也可能正在等待 CPU 时间片。
包含了操作系统线程状态中的 Running 和 Ready。
阻塞(Blocking)
阻塞状态是线程阻塞在进入synchronized
关键字修饰的方法或代码块时的状态。
无限期等待(Waiting)
阻塞在JUC包中Lock接口的线程状态是等待状态。
等待其它线程显式地唤醒,否则不会被分配 CPU 时间片。
限期等待(Timed Waiting)
无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒。
- 调用
Thread.sleep()
方法使线程进入限期等待状态时,常常用“使一个线程睡眠”进行描述。 - 调用设置了 Timeout 参数的
Object.wait()
方法使线程进入限期等待的状态,常常用“挂起一个线程”进行描述。 - 调用设置了 Timeout 参数的
Thread.join()
方法使线程进入限期等待的状态。 LockSupport.parkNanos()
方法,LockSupport.parkUntil()
方法。- 睡眠和挂起是用来描述行为,而阻塞和等待用来描述状态。
- 阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁。而等待是主动的,通过调用
Thread.sleep()
和Object.wait()
等方法进入。
死亡(Terminated)
可以是线程结束任务之后自己结束,或者产生了异常而结束。
2. 使用线程
有三种使用线程的方法:
- 实现 Runnable 接口;
- 实现 Callable 接口;
- 继承 Thread 类。
实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以说任务是通过线程驱动从而执行的。
实现 Runnable 接口
需要实现 run() 方法。
通过 Thread 调用 start() 方法来启动线程。
public class MyRunnable implements Runnable {
public void run() {
// ...
}
}
public static void main(String[] args) {
MyRunnable instance = new MyRunnable();
Thread thread = new Thread(instance);
thread.start();
}
实现 Callable 接口
与 Runnable 相比,Callable 可以有返回值,返回值通过 FutureTask 进行封装。
public class MyCallable implements Callable<Integer> {
public Integer call() {
// ...
return 123;
}
}
public static void main(String[] args) throws ExecutionException, Interrupted