- 写在前面的话
- 引言
- 第 1 章 对象入门
- 第 2 章 一切都是对象
- 第 3 章 控制程序流程
- 第 4 章 初始化和清除
- 第 5 章 隐藏实施过程
- 第 6 章 类再生
- 第 7 章 多形性
- 第 8 章 对象的容纳
- 第 9 章 违例差错控制
- 第 10 章 Java IO 系统
- 第 11 章 运行期类型鉴定
- 第 12 章 传递和返回对象
- 第 十三 章 创建窗口和程序片
- 第 14 章 多线程
- 第 15 章 网络编程
- 第 16 章 设计范式
- 第 17 章 项目
- 附录 A 使用非 JAVA 代码
- 附录 B 对比 C++和 Java
- 附录 C Java 编程规则
- 附录 D 性能
- 附录 E 关于垃圾收集的一些话
- 附录 F 推荐读物
14.5 回顾 runnable
在本章早些时候,我曾建议大家在将一个程序片或主 Frame 当作 Runnable 的实现形式之前,一定要好好地想一想。若采用那种方式,就只能在自己的程序中使用其中的一个线程。这便限制了灵活性,一旦需要用到属于那种类型的多个线程,就会遇到不必要的麻烦。
当然,如果必须从一个类继承,而且想使类具有线程处理能力,则 Runnable 是一种正确的方案。本章最后一个例子对这一点进行了剖析,制作了一个 RunnableCanvas 类,用于为自己描绘不同的颜色(Canvas 是“画布”的意思)。这个应用被设计成从命令行获得参数值,以决定颜色网格有多大,以及颜色发生变化之间的 sleep() 有多长。通过运用这些值,大家能体验到线程一些有趣而且可能令人费解的特性:
//: ColorBoxes.java // Using the Runnable interface import java.awt.*; import java.awt.event.*; class CBox extends Canvas implements Runnable { private Thread t; private int pause; private static final Color[] colors = { Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow }; private Color cColor = newColor(); private static final Color newColor() { return colors[ (int)(Math.random() * colors.length) ]; } public void paint(Graphics g) { g.setColor(cColor); Dimension s = getSize(); g.fillRect(0, 0, s.width, s.height); } public CBox(int pause) { this.pause = pause; t = new Thread(this); t.start(); } public void run() { while(true) { cColor = newColor(); repaint(); try { t.sleep(pause); } catch(InterruptedException e) {} } } } public class ColorBoxes extends Frame { public ColorBoxes(int pause, int grid) { setTitle("ColorBoxes"); setLayout(new GridLayout(grid, grid)); for (int i = 0; i < grid * grid; i++) add(new CBox(pause)); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } public static void main(String[] args) { int pause = 50; int grid = 8; if(args.length > 0) pause = Integer.parseInt(args[0]); if(args.length > 1) grid = Integer.parseInt(args[1]); Frame f = new ColorBoxes(pause, grid); f.setSize(500, 400); f.setVisible(true); } } ///:~
ColorBoxes 是一个典型的应用(程序),有一个构建器用于设置 GUI。这个构建器采用 int grid 的一个参数,用它设置 GridLayout(网格布局),使每一维里都有一个 grid 单元。随后,它添加适当数量的 CBox 对象,用它们填充网格,并为每一个都传递 pause 值。在 main() 中,我们可看到如何对 pause 和 grid 的默认值进行修改(如果用命令行参数传递)。
CBox 是进行正式工作的地方。它是从 Canvas 继承的,并实现了 Runnable 接口,使每个 Canvas 也能是一个 Thread。记住在实现 Runnable 的时候,并没有实际产生一个 Thread 对象,只是一个拥有 run() 方法的类。因此,我们必须明确地创建一个 Thread 对象,并将 Runnable 对象传递给构建器,随后调用 start()(在构建器里进行)。在 CBox 里,这个线程的名字叫作 t。
请留意数组 colors,它对 Color 类中的所有颜色进行了列举(枚举)。它在 newColor() 中用于产生一种随机选择的颜色。当前的单元(格)颜色是 cColor。
paint() 则相当简单——只是将颜色设为 cColor,然后用那种颜色填充整张画布(Canvas)。
在 run() 中,我们看到一个无限循环,它将 cColor 设为一种随机颜色,然后调用 repaint() 把它显示出来。随后,对线程执行 sleep(),使其“休眠”由命令行指定的时间长度。
由于这种设计方案非常灵活,而且线程处理同每个 Canvas 元素都紧密结合在一起,所以在理论上可以生成任意多的线程(但在实际应用中,这要受到 JVM 能够从容对付的线程数量的限制)。
这个程序也为我们提供了一个有趣的评测基准,因为它揭示了不同 JVM 机制在速度上造成的戏剧性的差异。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论