rabbit.start(); tortoise.start(); }
public void run() { String currentRunning; while (state==0) {
currentRunning=Thread.currentThread().getName();
//得到当前线程的名程
if(currentRunning.equals(\是兔子
try{
Thread.sleep((int)(Math.random()*RabbitRestTime)); }
catch(InterruptedException e){ } RabbitX+=RabbitSpeed; if(RabbitX>EndX) RabbitX=EndX; }
else if(currentRunning.equals(\是乌龟
try{
Thread.sleep((int)(Math.random()*TortoiseRestTime)
); }
catch(InterruptedException e){ } TortoiseX+=TortoiseSpeed;
if(TortoiseX > EndX) TortoiseX=EndX; }
if (RabbitX == EndX) state=1; else if ( TortoiseX == EndX) state=2; repaint(); } } } 【编程技巧】
(1) 创建两个代表兔子和乌龟的线程,根据线程名决定各自的速度和休息时间。 (2) 根据是否到达终点决定state值的变化; (3) 线程的run方法内的循环条件是state值为0。
样例2:编写选号程序,在窗体中安排6个标签,每个标签上显示0~9之间的一位数字,每位数字用一个线程控制其变化,点击“停止”按钮则所有标签数字停止变化。 【参考程序】
import java.awt.*; import java.awt.event.*;
public class MyFrame extends Frame{
MyLabel x[]=new MyLabel[6]; //安排6个标签,每个标签显示1个数字 Button control;
public MyFrame(String title) { super(title);
Panel disp=new Panel();
disp.setLayout(new FlowLayout()); for (int i=0;i<6;i++ ) { x[i]=new MyLabel(); disp.add(x[i]);
new Thread(x[i]).start(); }
add(\,disp);
control=new Button(\停止\); add(\,control); pack();
setVisible(true);
control.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { for(int i=0;i<6;i++) x[i].stop=true; } } ); }
public static void main(String args[]) { new MyFrame(\); }
class MyLabel extends Label implements Runnable{ int value;
boolean stop=false; public MyLabel(){ super(\); value=0; }
public void run() { for (; ; ) {
value=(int)(Math.random()*10); //产生一个0到9的数字
setText(Integer.toString(value)); try {
Thread.sleep(500); }
catch (InterruptedException e) { }
if (stop) //停止标记为true,退出循环,结束运行 break; } } }
}【编程技巧】
(1) 将每个标签定义为线程方式运行,在运行中利用随机数产生数字显示。 (2) 线程体为一个循环语句,只有当stop标记变量为true,则停止;
(3) 主程序中将所有标签定义存入一个数组,这样可以方便地对其进行控制,例如,在点击“停止”按钮时将所有标签对象的stop属性值设置为true。
1.4 上机完成编程任务
任务描述:完成下列编程任务,并将代码与实验报告一起交给教师。
? 基本题(必做)
1)编写一个可变颜色的标签,用一个按钮控制颜色的改变与停止。点击按钮颜色停止变化,再点击该按钮颜色又变化。颜色的变化可用随机数确定。
2)有一个南北向的桥,只能容纳一个人,现桥的两边分别有10人和12人,编制一个多线程序让这些人到达对岸,每个人用一个线程表示,桥为共享资源。在过桥的过程中显示谁在过桥及其走向。
3)编写一个图片播放程序,图片的文件名为 file01.jpg,file02.jpg,?filen.jpg, 其中n由命令行输入,要求用多线程自动播放。
? 提高题(选做其中一个)
1)编制一个秒针计时器,在画面包含一个文本框,显示秒针值,安排一个“开始”和“结束”按钮,点击“开始”按钮则开始计时,点击“结束”停止计时。时间的确定可借助日历对象实例方法实现,用get(Calendar.SECOND)方法得到秒值,用get(Calendar.MINUTE)方法得到分值,用get(Calendar.HOUR)方法得到小时值。计算从“开始”到“当前”的时间差即可确定花费的秒数。
【进一步思考】如何将秒针计时器设计为图形界面,绘制一个圆形秒表,秒表的一圈为60秒,根据花费的时间显示秒针的变化。
2) 编写生产者/消费者问题的应用程序。生产者以0~200ms的速度随机产生30个小写字母,消费者以0~2s的速度取出字母,并显示在屏幕上。
3)利用多线程求解某范围素数,每个线程负责10000范围. 线程1找1000-10000 线程2找10001-20000 线程3找20001-30000
另开辟一线程专门接收其他线程发送给它的数据(创建管道输入输出流),直到3个线程发送的数据均结束(结束标记)为止,接受的数据以文本形式写入到文件xyz.dat中。
1.5 思考题(必做)
任务描述:完成实验后,完成下列多选题
1)什么原因可导致线程停止执行。
A.有更高优先级的线程开始执行; B.线程调用了 wait()方法; C.线程调用了yield()方法; D.线程调用了 pause()方法; E.线程调用了 sleep() 方法。 2)哪个方法是实现Runnable接口所需的?
A.wait() B.run() C.stop() D.update() E.resume() 3)以下代码的调试结果为?
public class Bground extends Thread{ public static void main(String argv[]){ Bground b = new Bground(); b.run(); }
public void start(){
for (int i = 0; i <10; i++){
System.out.println(\ } } }
A.编译错误,没有定义线程的run方法;
B.由于没有定义线程的run方法,而出现运行错误; C. 编译通过,运行输出 values 0 to 9 D. 编译通过,运行无输出 4) 有关线程的叙述正确的有:
A.通过继承Thread类或实现Runnable接口,可以获得对类中方法的互斥锁定。 B. 可以获得对任何对象的互斥锁定。
C. 线程通过调用对象的synchronized 方法可取得对象的互斥锁定。 D. 线程调度算法是平台独立的。 5) 以下哪个是线程类的方法?
A.yield()
B. sleep(long msec) C. go() D. stop()
6) 以下哪个最准确描述synchronized关键字?
A.允许两线程并行运行,而且互相通信; B. 保证在某时刻只有一个线程可访问方法或对象; C. 保证允许两个或更多处理同时开始和结束; D. 保证两个或更多线程同时开始和结束。
1.7 实验总结