本书以丰富的实例、由浅至深的方式全面讲解如何用Java进行多线程编程。全书分三部分。第一部分(第1章~第10章)介绍基础概念,包括线程、线程组、Swing、线程同步、线程优先级、启动和终止线程、线程间通信等。第二部分(第11章~第18章)介绍一些重要的多线程编程技术,包括自运行对象、异常回调、线程池、完全超时、摆脱阻塞的I/O状态、先进先出(FIFO)队列以及运用类SureStop和BooleanLock等。第三部分为附录,提供了Thread API和ThreadGroup API的相关材料。\r\n\r\n 本书可以帮助具有Java基本编程知识的程序员学习多线程编程。 \r\n
\r\n
第一部分 线 程 \r\n\r\n 第1章 线程简介 3 \r\n\r\n 1.1 什么是线程 4 \r\n\r\n 1.2 为什么使用多线程 4 \r\n\r\n 1.2.1 与用户的更佳交互 4 \r\n\r\n 1.2.2 同步动作的模拟 5 \r\n\r\n 1.2.3 利用多处理器 5 \r\n\r\n 1.2.4 等待缓慢I/O操作时完成其他任务 5 \r\n\r\n 1.2.5 简化对象模型 6 \r\n\r\n 1.3 不宜采用多线程的场合 7 \r\n\r\n 1.4 Java的内置线程支持 7 \r\n\r\n 1.5 易于起步, 难以掌握 7 \r\n\r\n 第2章 一个简单的双线程实例 9 \r\n\r\n 2.1 扩展java.lang.Thread类 10 \r\n\r\n 2.2 覆盖run()方法 11 \r\n\r\n 2.3 创建新线程 12 \r\n\r\n 2.4 综合运用 13 \r\n\r\n 2.5 小结 14 \r\n\r\n 第3章 创建和启动线程 15 \r\n\r\n 3.1 使用Thread.currentThread() 16 \r\n\r\n 3.2 线程命名:getName()和setName() 18 \r\n\r\n 3.2.1 使用getName() 18 \r\n\r\n 3.2.2 使用setName() 21 \r\n\r\n 3.3 线程构造函数 22 \r\n\r\n 3.4 激活线程:start()和isAlive() 24 \r\n\r\n 3.5 使用Thread.sleep() 26 \r\n\r\n 3.6 小结 28 \r\n\r\n 第4章 实现Runnable接口与扩展Thread类 30 \r\n\r\n 4.1 可视定时器图形组件 31 \r\n\r\n 4.2 能扩展Thread和JComponent吗 37 \r\n\r\n 4.3 接口java.lang.Runnable 38 \r\n\r\n 4.4 把Runnable对象传递给Thread的构造函数 38 \r\n\r\n 4.5 修改SecondCounter来使用Runnable 39 \r\n\r\n 4.6 检查SecondCounter的准确性 45 \r\n\r\n 4.7 提高SecondCounter的准确性 49 \r\n\r\n 4.8 小结 54 \r\n\r\n 第5章 完美终止线程 55 \r\n\r\n 5.1 中断线程:interrupt() 56 \r\n\r\n 5.1.1 中断休眠线程 58 \r\n\r\n 5.1.2 待决中断 56 \r\n\r\n 5.1.3 使用isInterrupted() 59 \r\n\r\n 5.1.4 使用Thread.interrupted() 60 \r\n\r\n 5.1.5 使用InterruptedException 61 \r\n\r\n 5.2 挂起和恢复线程执行 63 \r\n\r\n 5.2.1 使用淘汰的方法suspend()和resume() 63 \r\n\r\n 5.2.2 在不恰当的时候挂起 67 \r\n\r\n 5.2.3 不使用淘汰方法实现挂起和恢复 70 \r\n\r\n 5.3 终止线程 74 \r\n\r\n 5.3.1 使用淘汰的方法stop() 74 \r\n\r\n 5.3.2 取代stop() 76 \r\n\r\n 5.4 stop(). suspend()和resume()的最佳替代 78 \r\n\r\n 5.5 守护线程 84 \r\n\r\n 5.6 小结 86 \r\n\r\n 第6章 线程优先化 87 \r\n\r\n 6.1 系统线程优先级 88 \r\n\r\n 6.2 线程优先级常量 89 \r\n\r\n 6.2.1 Thread.MAX_PRIORITY 89 \r\n\r\n 6.2.2 Thread.MIN_PRIORITY 89 \r\n\r\n 6.2.3 Thread.NORM_PRIORITY 89 \r\n\r\n 6.3 判断当前优先级:getPriority() 89 \r\n\r\n 6.4 更改线程的优先级:setPriority() 91 \r\n\r\n 6.5 线程状态 94 \r\n\r\n 6.6 优先级和规划 96 \r\n\r\n 6.7 自愿放弃处理器:Thread.yield() 96 \r\n\r\n 6.8 线程规划情形 102 \r\n\r\n 6.8.1 情形一:一个高优先级线程独占处理器 102 \r\n\r\n 6.8.2 情形二:所有高优先级线程独占处理器 102 \r\n\r\n 6.8.3 情形三:所有线程均获得一定的处理器时间 102 \r\n\r\n 6.9 小结 103 \r\n\r\n 第7章 并发访问对象和变量 104 \r\n\r\n 7.1 易变成员变量修饰符 105 \r\n\r\n 7.2 同步方法修饰符 110 \r\n\r\n 7.2.1 两个线程同时位于一个对象的同一个方法中 110 \r\n\r\n 7.2.2 同一时刻一个线程 112 \r\n\r\n 7.2.3 两个线程, 两个对象 115 \r\n\r\n 7.2.4 避免对象的意外崩溃 117 \r\n\r\n 7.2.5 对象处于不一致状态时, 推迟对它的访问 121 \r\n\r\n 7.3 同步语句块 126 \r\n\r\n 7.3.1 减少持有锁的时间 126 \r\n\r\n 7.3.2 锁定任意对象, 而非仅仅锁定当前对象 127 \r\n\r\n 7.3.3 把向量内容安全地复制到数组 128 \r\n\r\n 7.4 静态同步方法 130 \r\n\r\n 7.5 在同步语句中使用类级别锁 134 \r\n\r\n 7.6 同步化和集合API 136 \r\n\r\n 7.6.1 封装集合, 使之同步化 136 \r\n\r\n 7.6.2 安全地把列表中的内容复制到数组 137 \r\n\r\n 7.6.3 安全遍历集合元素 139 \r\n\r\n 7.7 死锁 141 \r\n\r\n 7.8 加速并发访问 145 \r\n\r\n 7.9 小结 145 \r\n\r\n 第8章 线程间通信 147 \r\n\r\n 8.1 线程间通信的必要性 148 \r\n\r\n 8.2 等待/通知机制 148 \r\n\r\n 8.2.1 最小规模的等待/通知 148 \r\n\r\n 8.2.2 典型等待/通知 150 \r\n\r\n 8.2.3 运用同步方法的等待/通知 151 \r\n\r\n 8.3 用于等待/通知的对象API 153 \r\n\r\n 8.3.1 notify() 153 \r\n\r\n 8.3.2 notifyAll() 153 \r\n\r\n 8.3.3 wait() 153 \r\n\r\n 8.3.4 wait(long) 154 \r\n\r\n 8.3.5 wait(long, int) 154 \r\n\r\n 8.4 何时使用notifyAll()代替notify() 154 \r\n\r\n 8.5 遗漏通知 155 \r\n\r\n 8.5.1 MissedNotify 155 \r\n\r\n 8.5.2 MissedNotifyFix 159 \r\n\r\n 8.6 早期通知 163 \r\n\r\n 8.6.1 EarlyNotify 164 \r\n\r\n 8.6.2 EarlyNotifyFix 167 \r\n\r\n 8.7 示例CubbyHole 171 \r\n\r\n 8.8 使用join()等待线程的消亡 177 \r\n\r\n 8.8.1 join() 177 \r\n\r\n 8.8.2 join(long) 177 \r\n\r\n 8.8.3 join(long, int) 177 \r\n\r\n 8.8.4 JoinDemo 178 \r\n\r\n 8.9 使用管道在线程间流动数据 181 \r\n\r\n 8.9.1 PipedBytes 182 \r\n\r\n 8.9.2 PipedCharacters 185 \r\n\r\n 8.10 使用ThreadLocal和InheritableThreadLocal 188 \r\n\r\n 8.10.1 ThreadLocal API 189 \r\n\r\n 8.10.2 ThreadID 189 \r\n\r\n 8.10.3 InheritableThreadLocal API 192 \r\n\r\n 8.10.4 InheritableThreadID 192 \r\n\r\n 8.11 小结 198 \r\n\r\n 第9章 线程和Swing 199 \r\n\r\n 9.1 为什么Swing工具包不是多线程安全 200 \r\n\r\n 9.2 使用SwingUtilities.invokeAndWait() 201 \r\n\r\n 9.3 使用SwingUtilities.invokeLater() 204 \r\n\r\n 9.4 使用SwingUtilities.isEventDispatchThread() 207 \r\n\r\n 9.5 何时不需要invokeAndWait()和invokeLater() 207 \r\n\r\n 9.6 在GUI设置中使用工作线程的必需性 208 \r\n\r\n 9.7 使用工作线程减轻事件线程的负担 213 \r\n\r\n 9.8 在自定义组件中滚动文本 220 \r\n\r\n 9.9 动画显示一系列图像 225 \r\n\r\n 9.10 在JLabel上显示流逝的时间 229 \r\n\r\n 9.11 在容器内浮动组件 233 \r\n\r\n 9.12 小结 238 \r\n\r\n 第10章 线程组 239 \r\n\r\n 10.1 什么是线程组 240 \r\n\r\n 10.2 使用getParent() 241 \r\n\r\n 10.3 查找线程组的子组 241 \r\n\r\n 10.4 使用Thread的getThreadGroup()方法 242 \r\n\r\n 10.5 查找线程组中的所有线程 242 \r\n\r\n 10.6 理解线程组的安全性 242 \r\n\r\n 10.7 使用setMaxPriority()和getMaxPriority() 243 \r\n\r\n 10.8 使用interrupt() 243 \r\n\r\n 10.9 淘汰的方法:stop(). suspend()和resume() 243 \r\n\r\n 10.10 类ThreadViewer 243 \r\n\r\n 10.11 小结 252 \r\n\r\n 第二部分 技 术 \r\n\r\n 第11章 自运行对象 255 \r\n\r\n 11.1 简单自运行类 256 \r\n\r\n 11.2 使用内部类来隐藏run() 259 \r\n\r\n 11.3 要考虑的额外功能 261 \r\n\r\n 11.4 小结 267 \r\n\r\n 第12章 异常回调 268 \r\n\r\n 12.1 ExceptionListener接口 269 \r\n\r\n 12.2 支持ExceptionListener的辅助方法 269 \r\n\r\n 12.3 小结 276 \r\n\r\n 第13章 线程池 277 \r\n\r\n 13.1 线程池的好处 278 \r\n\r\n 13.2 线程池的考虑与开销 278 \r\n\r\n 13.3 泛型线程池:ThreadPool 279 \r\n\r\n 13.4 专门工作线程池:HttpServer 288 \r\n\r\n 13.4.1 类HttpServer 289 \r\n\r\n 13.4.2 类HttpWorker 296 \r\n\r\n 13.4.3 服务文件示例 305 \r\n\r\n 13.4.4 用3个工作线程运行HttpServer 307 \r\n\r\n 13.4.5 用10个工作线程来运行HttpServer 309 \r\n\r\n 13.5 小结 310 \r\n\r\n 第14章 等待完全超时 311 \r\n\r\n 14.1 意外提前返回 312 \r\n\r\n 14.2 判断是否应当再次调用wait() 315 \r\n\r\n 14.3 通用等待-直到模式 319 \r\n\r\n 14.4 小结 325 \r\n\r\n 第15章 摆脱阻塞I/O状态的束缚 326 \r\n\r\n 15.1 read()方法忽略中断和终止请求 327 \r\n\r\n 15.2 关闭流来摆脱阻塞状态 329 \r\n\r\n 15.2.1 类CalcServer与摆脱阻塞的accept() 330 \r\n\r\n 15.2.2 类CalcWorker与摆脱阻塞的read() 333 \r\n\r\n 15.2.3 类CalcClient 336 \r\n\r\n 15.2.4 运行CalcClient的输出 337 \r\n\r\n 15.3 被中断时抛出InterruptedIOException 338 \r\n\r\n 15.3.1 类ThreadedInputStream 338 \r\n\r\n 15.3.2 类BufferedThreadedInputStream 347 \r\n\r\n 15.4 针对可中断I/O使用BufferedThreadedInputStream 349 \r\n\r\n 15.5 小结 354 \r\n\r\n 第16章 SureStop的运用 356 \r\n\r\n 16.1 使用SureStop的原则 357 \r\n\r\n 16.2 SureStop类 357 \r\n\r\n 16.3 使用SureStopVerbose的分析 363 \r\n\r\n 16.4 用SureStopDemo演示SureStop的工作方式 369 \r\n\r\n 16.5 小结 374 \r\n\r\n 第17章 类BooleanLock的运用 375 \r\n\r\n 17.1 背景 376 \r\n\r\n 17.2 类BooleanLock 376 \r\n\r\n 17.3 使用BooleanLock在线程间发送信号 380 \r\n\r\n 17.4 避免阻塞于同步 382 \r\n\r\n 17.4.1 SyncBlock 382 \r\n\r\n 17.4.2 InterruptibleSyncBlock 385 \r\n\r\n 17.5 使用TransitionDetector检测Value的短暂变化 388 \r\n\r\n 17.6 小结 394 \r\n\r\n 第18章 先进先出(FIFO)队列 395 \r\n\r\n 18.1 FIFO队列如何工作 396 \r\n\r\n 18.2 用数组实现FIFO 397 \r\n\r\n 18.3 用Java的简单实现:SimpleObjectFIFO 399 \r\n\r\n 18.4 对象引用的一个扩展FIFO队列:ObjectFIFO 405 \r\n\r\n 18.5 字节的FIFO队列:ByteFIFO 419 \r\n\r\n 18.6 小结 432 \r\n\r\n 第三部分 附 录 \r\n\r\n 附录A Thread API 435 \r\n\r\n 成员变量 436 \r\n\r\n Thread.MAX_PRIORITY 436 \r\n\r\n Thread.MIN_PRIORITY 436 \r\n\r\n Thread.NORM_PRIORITY 436 \r\n\r\n 构造函数 437 \r\n\r\n Thread(ThreadGroup, Runnable, String) 437 \r\n\r\n Thread(ThreadGroup, Runnable) 437 \r\n\r\n Thread(ThreadGroup, String) 437 \r\n\r\n Thread(Runnable, String) 437 \r\n\r\n Thread(Runnable) 438 \r\n\r\n Thread(String) 438 \r\n\r\n Thread() 438 \r\n\r\n 静态方法 438 \r\n\r\n Thread.activeCount() 438 \r\n\r\n Thread.currentThread() 438 \r\n\r\n Thread.dumpStack() 438 \r\n\r\n Thread.enumerate() 439 \r\n\r\n Thread.interrupted() 439 \r\n\r\n Thread.sleep(long) 439 \r\n\r\n Thread.sleep(long, int) 439 \r\n\r\n Thread.yield() 439 \r\n\r\n 实例方法 440 \r\n\r\n checkAccess() 440 \r\n\r\n destroy() 440 \r\n\r\n getContextClassLoader() 440 \r\n\r\n getName() 440 \r\n\r\n getPriority() 440 \r\n\r\n getThreadGroup() 440 \r\n\r\n interrupt() 441 \r\n\r\n isAlive() 441 \r\n\r\n isDaemon() 441 \r\n\r\n isInterrupted() 441 \r\n\r\n join() 441 \r\n\r\n join(long) 441 \r\n\r\n join(long, int) 442 \r\n\r\n run() 442 \r\n\r\n setContextClassLoader(ClassLoader) 442 \r\n\r\n setDaemon(boolean) 442 \r\n\r\n setName(String) 442 \r\n\r\n setPriority(int) 443 \r\n\r\n start() 443 \r\n\r\n toString() 443 \r\n\r\n 被淘汰的方法 443 \r\n\r\n countStackFrames() 443 \r\n\r\n resume() 443 \r\n\r\n stop() 444 \r\n\r\n stop(Throwable) 444 \r\n\r\n suspend() 444 \r\n\r\n 附录B ThreadGroup API 445 \r\n\r\n 构造函数 446 \r\n\r\n ThreadGroup(ThreadGroup, String) 446 \r\n\r\n ThreadGroup(String) 446 \r\n\r\n 实例方法 447 \r\n\r\n activeCount() 447 \r\n\r\n activeGroupCount() 447 \r\n\r\n checkAccess() 447 \r\n\r\n destroy() 447 \r\n\r\n enumerate(Thread[], boolean) 447 \r\n\r\n enumerate(Thread[]) 448 \r\n\r\n enumerate(ThreadGroup[], boolean) 448 \r\n\r\n enumerate(ThreadGroup[]) 448 \r\n\r\n getMaxPriority() 448 \r\n\r\n getName() 448 \r\n\r\n getParent() 448 \r\n\r\n interrupt() 449 \r\n\r\n isDaemon() 449 \r\n\r\n isDestroyed() 449 \r\n\r\n list() 449 \r\n\r\n parentOf(ThreadGroup) 449 \r\n\r\n setDaemon(boolean) 449 \r\n\r\n setMaxPriority(int) 449 \r\n\r\n toString() 450 \r\n\r\n uncaughtException(Thread, Throwable) 450 \r\n\r\n 被淘汰的方法 450 \r\n\r\n allowThreadSuspension(boolean) 450 \r\n\r\n resume() 450 \r\n\r\n stop() 450 \r\n\r\n suspend() 451 \r\n\r\n 索引 452 \r\n
\r\n
随着Java2一系列新技术(如Java2D. Java3D. Swing. JavaSound. EJB. Servlet. JSP. CORBA. XML. JNDI等)的引入, 以及VM安全策略的不断完善和效率不断提高, Java阵营越来越庞大, Java在电子商务以及金融. 证券. 电信等各个行业中的应用越来越广泛.
几乎每一位Java程序员都知道Java语言具有很多出色的特点:简单. 面向对象. 自动内存管理. 分布式计算. 稳定. 安全. 解释执行. 结构中立. 平滑移植以及异常处理等, 让诸多开发人员尤其推崇的是它对多线程的天生支持.
本书正是一本讲解Java多线程编程的专著. 本书内容几乎涉及了Java多线程编程的各个方面. 第一部分着重介绍基本概念, 第二部分详细地介绍了一些线程技术. 第三部分附录提供了Thread API和Thread Group API的相关资料.
读者要注意, 本书示例使用的开发包为Java SDK标准版1. 2. 现在的主流版本是1. 4. 所有例子在1. 4版本下仍能正常运行. 针对多线程编程, 版本从1. 2到1,4没有实质性的变化, 主要是修正一些Bug, 提升线程的性能. 在不同版本间开发. 调试Java多线程应用程序(甚至要综合考虑未来版本的新特点)有许多地方仍然值得读者关注, 如:
● 版本较低的JDK不支持非阻塞I/O API. 从JDK 1. 4开始引入了非阻塞的I/O库(java. nio).
● 从1. 2版开始, JDK中就加入了java. lang. Thread Local类.
● 从下一个版本JDKl. 5开始, 又要提供关于线程. 并发等新性能的支持. 读者可以从Sun Microsystems公司网站了解相关信息.
● Doug Lea编写了一个极其优秀的免费并发实用程序包, 它包括并发应用程序的锁. 互斥. 队列. 线程池. 轻量级任务. 有效的并发集合. 原子的算术操作和其他基本组件. 该包将成为下一个版本JDK1. 5中java. util. concurrent包的基础.
● 为了提升JDK1. 2中Thread Local的性能, JDK1. 3对它进行了重写, JDK1. 4又重写了一次.
Java对多线程的支持对程序员来说无疑是幸运的, 但较难掌握. 容易出错, 使很多人终日苦恼. 相信这本书能成为采用Java多线程编程的程序员的良师益友.
由于译者水平有限, 且时间仓促, 错误在所难免, 希望广大读者不吝指正. 我的联系E-mail:web_zhou@21cn. com.
译者
2003年8月16日
本书结构
本书面向的读者是那些已经开始使用Java语言, 而且需要开发多线程应用程序和applet(小应用程序)的人. 读者可以没有任何线程编程方面的背景, 因此本书开始使用的示例简单易懂, 随着讲解的深入, 以后章节逐渐切入高级主题, 并且完全涵盖Java线程编程的所有方面. 本书的第二部分重点演示不同的高级技巧, 它们可以马上用于实战. 第1章-第10章可以按顺序阅读, 因为每一章的讲解均是以前一章介绍的概念为基础的. 第11章—第18章讨论的技术可以按任意顺序跳跃式地学习. 一些技术相当有用, 演示其他技术时, 也用到了这些重要的技术, 因此, 可以在碰到这些技术时, 再研读它们.
本书中的例子用Sun Microsystems的Java 2 SDK, 标准版1. 2(即JDK1. 2)开发而成. 开发包(Kit)的推荐运行环境:CPU最低为Intel奔腾166MHz, 操作系统为微软Windows 95或更新版本. 为了起强调作用, 书中代码清单中的一些语句用黑体字排版. 源代码文件可以从www. samspublishing. com下载. 进入网站后, 通过搜索引擎可以找到本书相关资源, 方法是:在搜索引擎的左边文本框中填入本书的ISBN号(0672315858), 在右边下拉框中选择“ISBN”, 再点击“search”按钮即可以找到本书的资源链接.
下面为各章概要.
第1章:线程简介
第1章简介多线程编程以及如何在Java中使用线程. 解释为什么需要线程, 如何利用线程提高应用程序的性能.
第2章:一个简单的双线程实例
在第2章, 可以看到最基本的Java多线程应用实例. 在这些应用程序中, 有两个线程同时运行并打印各自的信息. 这一章将演示创建一个新线程所需的步骤.
第3章:创建和启动线程
第3章开始探讨类Thread的APl. 在这一章将学习如何获得当前执行线程的句柄, 如何命名线程, 如何检查线程是否仍然激活以及如何暂时将线程设置成休眠状态.
第4章:实现Runnable接口与扩展Thread类
在第4章, 使用接口Runnable来演示让对象中某个线程运行的第二种方式. 对于缺少多重继承的Java环境, 这是一个特别重要的特征.
第5章:完美终止线程
第5章演示如何终止线程的运行. 这一章将介绍一些完美和安全的办法, 以替代JDK1. 2中一些被淘汰的方法.
第6章:线程优先化
第6章演示如何在Java虚拟机上给线程分配优先级以及优先级对线程规划的影响.
第7章:并发访问对象和变量
当多个线程同时运行时, 务必确保线程相互间能够安全交互. 第7章将说明防止可能导致数据崩溃的竞争条件的具体步骤. 这一章演示了关键字synchronized和volatile的正确使用. 还演示如何以一种线程安全方式在Collections API中使用类.
第8章:线程间通信
让多线程与共享数据安全交互时, 需要运用一种途径, 让一个线程通知另一个线程数据已经更改. 第8章演示如何使用wait(). notify()和notifyAll()在应用程序的线程间发送通知. 还讨论了join(). 管道和变量Thread Local的使用.
第9章:线程和Swing
第9章讲解如何通过图形用户界面在应用程序中使用多线程. Swing工具包不能确保原有多线程安全, 这一章将演示安全使用Swing的必需步骤.
第10章:线程组
第10章探讨Thread Group API以及给组分配线程的方式.
第11章:自运行对象
从第11章开始介绍技术部分. 这一章首先演示如何创建一个类, 在构建过程中能够自动启动一个内部线程. 运用这一技术, 用户不必知道是否对象内存在运行的线程.
第12章:异常回调
第12章演示如何查找已经抛出异常的另一个线程.
第13章:线程池
第13章讨论如何在执行短小代码运行块时, 共享线程池中的线程. 这一章演示如何编写一个简单的Web页服务器, 让它使用共享线程池为客户的页面请求服务.
第14章:等待完全超时
学习第8章时可以发现, 判断线程是否受到另一个线程的通知, 或者超时等待被通知, 这一任务并非总是那么容易. 第14章将讲解一种技术, 可以用于确保线程等待完全超时值.
第15章:摆脱阻塞I/O状态的束缚
在完成数据的写或读之前, Java中大部分I/O运算都处于阻塞状态. 不方便的是, 阻塞的I/O方法不会对中断做出反应. 第15章将介绍一些处理这类情况的技术.
第16章:类SureStop的运用
第16章演示运用类SureStop来确保线程的最终消亡.
第17章:类BooleanLock的运用
第17章演示一种把等待/通知机制封装到一个紧凑. 多线程安全类中的技术, 这个类可以在多线程应用程序的多个地方重用.
第18章:先进先出(FIPO)队列
第18章演示如何构建一个在多线程环境中安全使用的FIFO队列. 尤其是, 这一章要讲解如何创建一个FIFO队列来保存对象引用以及如何创建一个FIFO队列来保存字节.
附录:线程API与线程组API
本书末尾提供了两部分附录. 附录A解释类Thread的API:附录B解释类ThreadGroup的API.
本书约定
本书使用不同的排版方式来匹配代码与常规文字, 也有助于读者注意一些重要的概念.
用户输入的文本(包括程序代码)以及应当出现在屏幕上的文本用如下字体:
It will look like this to mimic the way text looks on your screen.
代码行前面的箭头(-)表示代码行太长, 因此分排为2行. 实际编译代码时, 应该将此行与前一行当成完整代码行.