- 一个 Java 程序的运行,不仅仅是
main()
方法的运行,而是 main 线程和多个其他线程的同时运行。
- 针对频繁阻塞(休眠或 I/O 操作)的线程需要设置较高优先级,而偏重计算的线程则设置较低优先级,避免处理器被独占。
- 线程优先级不能作为程序正确性的依赖,因为操作系统可以完全不用理会 Java 线程对优先级的设定。
- 线程状态
- NEW:初始状态,线程被构建,但是还没调用 start()方法。
- RUNNABLE:运行状态,Java 线程将操作系统中的就绪和运行两种状态笼统地称作“运行中”。
- BLOCKED:阻塞状态,表示线程阻塞于锁。
- WAITING:等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或中断)。
- TIME_WAITING:超时等待状态,该状态不同于 WAITING,它可在指定时间自行返回。
- TERMINATED:终止状态,表示当前线程已经执行完毕。
- Daemon 线程:支持型线程,当 Java 虚拟机不存在非 Daemon 线程时,Java 虚拟机将会退出,但当 Java 虚拟机退出时,Daemon 线程中的 finally 块不一定会执行。
- suspend()方法不会释放已经占有的资源(比如锁),而是占着资源进入睡眠状态,容易引发死锁问题;stop()方法在终结一个线程时不会保证线程资源的正常释放,因此可能导致程序工作不确定,因而 suspend()、stop()和 resume()方法已经不建议使用。
- 优雅中止线程:boolean 变量(标志位)或 interrupt()方法。
- 等待/通知机制:作用于一个对象修改了值,另一个线程感知到变化,进行相应操作的场景。
- notify():通知一个在对象上等待的线程,使其从 wait()方法返回,前提是该线程获取到了对象的锁。
- notifyAll():通知所有等待在该对象上的线程。
- wait():调用该方法的线程进入 WAITING 状态,只有等待另外线程的通知或被中断才会返回,调用该方法后会释放对象的锁。
- wait(long):超时等待一段时间,参数是毫秒。
- wait(long, int):对于超时时间更细粒度控制,可达纳秒。
- 等待方(消费者)遵循:获取对象的锁 → 如果条件不满足,调用 wait(),被通知后仍要检查条件 → 条件满足则执行对应逻辑。
- 通知方(生产者)遵循:获取对象的锁 → 改变条件 → 通知所有等待在对象上的线程。
// 等待方/消费者
synchronized(对象) {
while(条件不满足) 对象.wait()
// 展开对应处理逻辑
}
// 通知方/生产者
synchronized(对象) {
// 改变条件
对象.notifyAll()
}
- 管道输入/输出:
- 面向字节:PipedOutputStream、PipedInputStream。
- 面向字符:PipedReader、PipedWriter。
- 输入输出流使用前需要先绑定,即调用 connect()方法,否则将抛出异常。
- Thread.join():当前线程等待 Thread 线程终止后,才从 join()方法返回。
- 实现遵循加锁、循环和处理逻辑三个步骤。
- 线程终止时,会调用线程自身的 notifyAll()方法,通知所有等待在该线程对象上的线程。
- ThreadLocal:线程变量,以 ThreadLocal 对象为键,任意对象为值的存储结构,一个线程可以根据一个 ThreadLocal 对象查询到绑定在这个线程上的一个值。