Java线程:
- 守护线程——不影响JVM的正常停止,常用于执行一些重要性不太高的任务
- 用户线程——
创建一个Thread实例与创建其他类实例的区别:
JVM为Thread实例分配两个调用栈所需的存储空间:
- 跟踪Java代码间的调用关系
- 跟踪Java代码对本地代码(Native代码)的调用关系
一个Thread实例通常对应两个线程:
- JVM线程
- 本地(Native)线程
Java语言中,子线程是否是一个守护线程取决于父线程:默认与父线程相同。可以在子线程启动前调用Thread实例的setDaemon方法来修改。
Java线程的状态:
- New:新建未启动
- RUNNABLE: READY && RUNNING
- BLOCKED:阻塞式I/O或试图获取一个其他线程持有的锁
- WAITING: Object.wait()、Thread.join()和LockSupport.park()
Object.notify()、Object.nodifyAll()和LockSupport.unpart(thread) - TIMED_WAITING:与WAITING类似,但是有时间限制
- TERMINATED:已经执行结束
上下文切换
保存线程上下文(包括CPU寄存器和程序计数器内容等),恢复线程上下文
上下文切换会带来额外的开销,这包括:
- 保存和恢复线程上下文信息的开销
- 对线程进行调度的CPU时间开销
- CPU缓存内容失效的开销
synchronized:
- 通过该关键字所包括的临界区的排他性保证在任何一个时刻只有一个线程能够执行临界区的代码。
- 保证操作的原子性和内存可见性。
- 会导致上下文切换。
volatile:
- 写入主存,且缓冲区的缓冲失效,保证操作的可见性。
- 禁止指令重排序。
多线程优势:
- 提高系统吞吐率
- 提高响应性
- 充分利用多核CPU资源
- 最小化对系统资源的使用
- 简化程序的结构
多线程风险:
- 线程安全问题
- 死锁、活锁、饥饿问题
- 上下文切换
- 可靠性