CPU“
全心全意”为那些计算服务,所以对用户的输入十分迟钝,几乎没有什么
反应。在这里,我们用一个合成的
applet/application
(程序片/应用程序)来简
单显示出一个计数器的结果:
752-753
页程序
在这个程序中,
AWT
和程序片代码都应是大家熟悉的,第
13
章对此已有很
详细的交待。
go()
方法正是程序全心全意服务的对待:将当前的
count
(计数)
值置入
TextField
(文本字段)
t
,然后使
count
增值。
go()
内的部分无限循环是调用
sleep()
。
sleep()
必须同一个
Thread
(线程)对
象关联到一起,而且似乎每个应用程序都有部分线程同它关联(事实上,
Java
本身就是建立在线程基础上的,肯定有一些线程会伴随我们写的应用一起运行)。
所以无论我们是否明确使用了线程,都可利用
Thread.currentThread()
产生由程序
使用的当前线程,然后为那个线程调用
sleep()
。注意,
Thread.currentThread()
是
Thread
类的一个静态方法。
注意
sleep()
可能“掷”出一个
InterruptException
(中断违例)——尽管产生
这样的违例被认为是中止线程的一种“恶意”手段,而且应该尽可能地杜绝这一
做法。再次提醒大家,违例是为异常情况而产生的,而不是为了正常的控制流。
在这里包含了对一个“睡眠”线程的中断,以支持未来的一种语言特性。
一旦按下
start
按钮,就会调用
go()
。研究一下
go()
,你可能会很自然地(就
象我一样)认为它该支持多线程,因为它会进入“睡眠”状态。也就是说,尽管
方法本身“睡着”了,
CPU
仍然应该忙于监视其他按钮“按下”事件。但有一
个问题,那就是
go()
是永远不会返回的,因为它被设计成一个无限循环。这意味
着
actionPerformed()
根 本 不 会 返 回 。 由 于 在 第 一 个 按 键 以 后 便 陷 入
actionPerformed()
中,所以程序不能再对其他任何事件进行控制(如果想出来,
必须以某种方式“杀死”进程——最简便的方式就是在控制台窗口按
Ctrl
+
C
键)。
这里最基本的问题是
go()
需要继续执行自己的操作,而与此同时,它也需要
返回,以便
actionPerformed()
能够完成,而且用户界面也能继续响应用户的操作。
但对象
go()
这样的传统方法来说,它却不能在继续的同时将控制权返回给程序的
其他部分。这听起来似乎是一件不可能做到的事情,就象
CPU
必须同时位于两
个地方一样,但线程可以解决一切。“线程模型”(以及
Java
中的编程支持)是
一种程序编写规范,可在单独一个程序里实现几个操作的同时进行。根据这一机
制,
CPU
可为每个线程都分配自己的一部分时间。每个线程都“感觉”自己好
象拥有整个
CPU
,但
CPU
的计算时间实际却是在所有线程间分摊的。
线程机制多少降低了一些计算效率,但无论程序的设计,资源的均衡,还是
用户操作的方便性,都从中获得了巨大的利益。综合考虑,这一机制是非常有价
值的。当然,如果本来就安装了多块
CPU
,那么操作系统能够自行决定为不同
的
CPU
分配哪些线程,程序的总体运行速度也会变得更快(所有这些都要求操
作系统以及应用程序的支持)。多线程和多任务是充分发挥多处理机系统能力的
一种最有效的方式。
14.1.1
从线程继承
为创建一个线程,最简单的方法就是从
Thread
类继承。这个类包含了创建和
运行线程所需的一切东西。
Thread
最重要的方法是
run()
。但为了使用
run()
,必
评论