然后,我们再执行命令:
|
程序的输出如下图所示:
图13-17 程序testThread.java的输出
你看,三个人在赛跑!看谁快,他们太接近了,谁是第一名呢?所以我们来看看在DOS窗口的输出:
图13-18 MS-DOS下的输出
我们看到,程序的输出给出了公正的判决。第一次赛跑(第一次运行这个程序),冠军是第三道(Racer #2),第一道(Racer #0)屈居第二,第二道(Racer #1)是最后一名。第二次赛跑时,第二道反而成为了第一名。我们再运行几次程序,就会发现每一次的成绩都可能不同。你来可以使用以下命令来让更多的“人”参加赛跑:
|
传授新知
这个程序太庞大了,也许会把大家吓倒!我们来看一下这个程序结构。这个示例由两个文件组成:testThread.java和Threader.java。
其中,Threader中定义了竞赛者对象,我们先一起来看一下这个类:
1)
|
这是类Threader中构造器方法,它为Threader设置对象名。
2)
|
我们为Threader类定义了一个paint方法,我们看一下这个方法做了些什么:
前两条语句用来画出这个竞赛者(Threader)的赛道,一条黑色的赛道!这条赛道用一根线来表示:它从(0,getSize().height/2)到(getSize().width,getSize().height/2)。也就是一个从最左边到最右边的,位于中心的黑线。
然后,我们画出这个竞赛者,它用一个黄色的椭圆来表示。这个椭圆宽15,高为整个格子,位置由变量myPosition决定。
一些提示:
我们将myPosition的初值设置为0.将整个赛道分成numberofSteps步,即600步。MyPosition每加1,就走过一步。
2)
|
这是一个while循环,当myposition小于numberofSteps,就将myposition加1(往前走一步),然后重画(这样这一步就会显示出来)。
如果myposition=numberofSteps时,意味着什么?对,意味着走完了赛程,因此,打印出完成信息。
大家看到,我们重画后,我们使用了这样一条语句:
|
这是让当前线程进入休眠状态一小会(10个时间周期)。这是为什么呢?要理解这个问题,我们需要学习一下CPU是如何管理这些线程的。线程与进程一样有三种状态:
§ 运行态:线程正在运行;
§ 就绪态:线程一切就绪,可以运行,正在等待CPU运行;
§ 阻塞态:线程未准备就绪,正在等待某个条件。
其间的关系,如下图所示:
图13-19 线程状态转换图
由于在单处理器的系统中,一个时间内CPU只能运行一个线程。所以如果我们在每个竞赛者跑一步时,就让它休眠(进入阻塞态,等待休眠时间到),这样就不会让一个线程一直占用CPU,以免不公平嘛!
由于我们让线程的休眠时间比较短,所以一会就回到了,这时线程就进入就绪态,等待CPU有时间的时候运行。CPU呢一有时间,就从就绪的线程中选择一个来运行。
大家看到这里,可能早已昏头转向了,下面我们举一个生活中的例子来模拟一下这个情况:有三位职员(对应程序中的三个竞赛者、即三个线程)要向经理(对应运行线程的CPU)汇报工作。但这个经理采用了一个十分公平的方法(当然在现实生活中是不可能的)来接受三个职员的汇报。也就是每一个职员一次只说一句话(每一个竞赛者跑一步),然后就呆一边休息一下(休眠10个时间周期),然后从另两个职员中任选一个来说(选择就绪的线程)。也是说一句话,就让他休息。这样周而复始,直到他们都汇报完毕。
情况如下图所示:
图13-20 竞赛者线程示意图
一些提示:
以上所述的关于线程的描述,是基于支持多线程的系统。如果不支持多线程的话,这是不成立的。在不支持线程的系统中,则将线程改成进程就行了。