Java线程模型
Java 运行时在很多方面依赖线程,类库设计也按多线程来考虑。实际上 Java 用线程让整个环境异步,避免 CPU 空转浪费。
对照单线程更容易看清优势。单线程常用轮询事件循环:一条线程在无限循环里询问事件序列,决定下一步。一旦某处理程序占住,别的事件只能等。线程因为等资源阻塞时,整个程序停住。
一、多线程取消轮询
Java 多线程的优点是取消主循环 / 轮询。一条线程可以暂停而不拖垮其他部分:等网络、等用户输入的空闲可以给别人用。动画循环可以每帧间隙睡一秒,而不暂停整个系统。出现阻塞时,只挂起那一条线程。
二、线程的几种状态
线程可以正在运行(running),只要拿到 CPU 就能跑。运行中的线程可以被挂起(suspend)临时中断,之后再恢复(resume)从停下的地方继续。等资源时会被阻塞(block)。任何时候都可以终止(terminate);一旦终止就不能再恢复。
| 状态 | 含义 |
|---|---|
| running | 获得 CPU 时间即可执行 |
| suspend / resume | 临时中断,再从停下处继续(现代 API 已不推荐直接 suspend) |
| block | 等待资源时挂起执行 |
| terminate | 立即中断,不能恢复 |
三、优先级与上下文转换
Java 给每个线程一个整型优先级,用来决定何时从一条运行中的线程切到另一条,这叫上下文转换(context switch)。单独一条线程时,优先级高并不等于跑得更快。
-
线程可以主动放弃控制(IO、sleep、阻塞、yield)。此时就绪队列里优先级最高的获得 CPU。 -
高优先级线程可以抢占:低优先级即使不让,也会被先占。这叫有优先权的多任务。 -
同优先级时,Windows 一类系统常按时间片轮转;Solaris 2.x 一类则依赖线程主动放弃,否则对等线程可能跑不到。
警告:不同操作系统下,等优先级线程的上下文转换行为可能不一样,据此写逻辑容易出错。
四、同步、消息与 Thread / Runnable
多线程引入异步行为,共享链表这类结构时必须防止一个线程在写、另一个在读。Java 在管程(monitor,C.A.R. Hoare 提出)模型上提供语言级同步:没有单独的 Monitor 类,每个对象都有隐式管程;调用同步方法时自动进入。一条线程待在某对象的同步方法里时,其他线程不能再调该对象的同步方法。
线程拆开之后要定义联系。别的语言常靠操作系统做线程间通信,成本高。Java 通过对象上预定的方法,让一条线程进入同步方法后 wait,直到另一条明确 notify 它出来。
多线程建立在 Thread 类及其伙伴接口 Runnable 上。Thread 封装线程的执行;你不能直接引用运行中线程的状态,只能通过代理(Thread 实例)操作。要创建新线程,程序必须扩展 Thread 或实现 Runnable。到目前为止的例子都是单线程;后面从所有 Java 程序都有的那条线——主线程——开始讲如何创建和管理。
一句话总结:多线程用暂停换轮询,阻塞只停一条;优先级决定何时切换,共享数据靠对象隐式管程,新建线程要么 extend Thread,要么 implement Runnable。
转载请注明来源:Java线程模型









