0x01 java多线程编程方法
例1:龟兔赛跑
import java.awt.*;
import java.awt.event.*;
public class Hello2 extends Canvas implements Runnable {
String name;
int speed;
int sleepTime;
final int distance=700;
int pos=0;
public Hello2(String n,int s,int t) {
name=n;speed=s;sleepTime=t;
}
public static void main(String args[]) {
Frame m=new Frame("龟兔赛跑");
m.setLayout(new GridLayout(3,1));
final Hello2 a1=new Hello2("乌龟",1,40);
final Hello2 a2=new Hello2("兔子",4,160);
Button b=new Button("开始");
m.add(a1);m.add(a2);m.add(b);//添加两个画布和一个按钮
m.setSize(780,200); m.setVisible(true);
b.addActionListener(new ActionListener() {//对按钮进行监听
public void actionPerformed(ActionEvent e) {
new Thread(a1).start();//创建两个线程同时启动
new Thread(a2).start();
a1.repaint(); a2.repaint();//repaint()是重绘component的方法;重绘组件,是一个具有刷新效果的方法
}
});
}
public void paint(Graphics g) {
g.drawString(name, 20, 20);//画出乌龟和兔子的两个名字
}
public void run() {
long startTime=System.currentTimeMillis();//记录开始时间
Graphics g=getGraphics();//得到画笔
while(pos<distance) {
for(int k=0; k<(int)(1+Math.random()*3);k++) {//k用随机数表示每次一口气跑了几秒
pos+=speed;
if(pos>distance) pos=distance;
g.fillRect(50,15,pos,10);
}
try {//跑了一段休息一会
Thread.sleep(sleepTime);
}catch(InterruptedException e) {}
}
long spend=System.currentTimeMillis()-startTime;//现在时间-开始时间=最终时间
javax.swing.JOptionPane.showMessageDialog(null, name+":花费"+spend+"毫秒");//通过消息框输出花费时间
pos=0;
repaint();
}
}
0x02 线程资源的同步处理
例2:过桥问题
class PersonPassBridge extends Thread {
private Bridge bridge;//桥对象
String id;//人的标识
public PersonPassBridge(String id,Bridge b) {
bridge=b;this.id=id;
}
public void run() {
bridge.getBridge();//等待过桥
System.out.println(id+"正过桥……");
try {
Thread.sleep((int)(Math.random()*1000));
}catch(InterruptedException e) {}
bridge.goDownBridge();//下桥
}
}
class Bridge{
private boolean engaged=false;//桥的占用状态
//synchronized执行某方法时对桥进行加锁
public synchronized void getBridge() {//取得上桥
while(engaged) {
try {
wait();//等待
}catch(InterruptedException e) {}
}
engaged =true;//占用桥
}
public synchronized void goDownBridge() {//下桥
engaged=false;
notifyAll();//唤醒其他等待线程
}
}
public class Hello2{
public static void main(String args[]) {
Bridge b=new Bridge();
PersonPassBridge x;
for(int k=1;k<=6;k++) {
x=new PersonPassBridge("南边,第"+k+"人",b);
x.start();
}
for(int k=1;k<=5;k++) {
x=new PersonPassBridge("北边,第"+k+"人",b);
x.start();
}
}
}
输出结果:
课后练习:利用多线程实现两个会计数的按钮,按钮上的数字随着线程的运行从100开始不断增加. 点击按钮,则相应按钮上的数字停止变化.
import java.awt.*;
import java.awt.event.*;
class CountButton extends Button implements Runnable,ActionListener {
int count=100;
boolean flag=true;
public CountButton(String s) {
super(s);//super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)
//this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
addActionListener(this);//按钮监听
}
public void actionPerformed(ActionEvent e) {
flag = false;//点击按钮,flag=false,那么while将会停止,即计数停止
}
public void run() {
while(flag && count < 10000)
{
try {
this.setLabel(""+ count++);
Thread.sleep((int)(1000*Math.random()));
}catch(Exception e) { }
}
}
}
public class Hello2 extends Frame{
public Hello2() {
setLayout(null);//不使用布局管理
CountButton t1=new CountButton("first");//创建按钮
t1.setBounds(30,50,80,40);///规定部件的坐标位置和宽度、高度
add(t1);//添加按钮
CountButton t2=new CountButton("Second");
t2.setBounds(130,50,80,40);
add(t2);
(new Thread(t1)).start();//创建线程,将计数按钮传递给线程
(new Thread(t2)).start();
}
public static void main(String args[]) {
Frame f=new Hello2();
f.setSize(250, 150);
f.setVisible(true);
}
}
输出结果: