多线程学习笔记1——创建线程和应用小案例
Thread类定义了多种方法管理线程,以下是几种常用方法:
方法 | 意义 |
---|---|
getName() | 获得线程名称 |
getPriority() | 获得线程优先级 |
isAlive() | 判断线程是否在运行 |
join() | 等待一个线程终止 |
run() | 线程的入口点 |
sleep() | 在一段时间内挂起线程 |
start() | 通过调用运行方法来启动线程 |
创建线程
可以通过继承Thread类(创建Thread类的子类),重写run(),加入线程所要执行的代码。当调用对象实例的start方法时,自动调用类中定义的run()方法启动对象线程运行。
还可以通过实现Runnable接口创建线程,Runnable接口中只有一个run()方法,实现该接口的方法将线程代码写在其中就完成了这一部分的任务。但是Runnable接口没有任何对线程的支持,所以还必须创建Thread类的实例,通过Thread类的构造函数public Thread(Runnable target)来实现:
new Thread(new MyThread()).start()
例1
该例创建了3个线程,分别等待1,2,3秒输出计数
public class Consumer extends Thread{
int nTime;
String strConsumer;
int count;
public Consumer(int nTime,String strConsumer){
this.nTime = nTime;
this.strConsumer = strConsumer;
count = 0;
}
public void run(){
while(true){
try{
System.out.println("消费者姓名"+strConsumer+".");
Thread.sleep(nTime);
}catch (Exception e){
e.printStackTrace();
}
if(count++>3) break;
}
}
public static void main(String[] args) {
Consumer aConsumer = new Consumer(1000,"A");
aConsumer.start();
Consumer bConsumer = new Consumer(2000,"B");
bConsumer.start();
Consumer cConsumer = new Consumer(3000,"C");
cConsumer.start();
}
}
main中依次调用的a,b,c实例,输出结果不是先全a,后b,后c,而是不同线程按照等待时间分别输出,由此可体现出创建的3个线程同时运行
例2——多线程应用小案例
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
class SeparateSubTask extends Thread{
private int count = 0;
private Counter2 c2;
private boolean runFlag = true;
public SeparateSubTask(Counter2 c2){
this.c2 = c2;
start();
}
public void invertFlag(){
if(runFlag)
runFlag = false;
}
public void run(){
while (true){
try {
sleep(100);
}catch (InterruptedException e){}
if (runFlag)
c2.t.setText(Integer.toString(count++));
}
}
}
public class Counter2 extends Applet{
TextField t = new TextField(10);
private SeparateSubTask sp = null;
private Button
onOff = new Button("end"),
start = new Button("start");
public void init(){
add(t);
start.addActionListener(new StartL());
add(start);
onOff.addActionListener(new OnOffL());
add(onOff);
}
class StartL implements ActionListener{
public void actionPerformed(ActionEvent e){
if(sp == null);
sp = new SeparateSubTask(Counter2.this);
}
}
class OnOffL implements ActionListener{
public void actionPerformed(ActionEvent e){
if(sp != null)
sp.invertFlag();
}
}
public static void main(String[] args){
Counter2 applet = new Counter2();
Frame aFrame = new Frame("计数器");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
aFrame.add(applet,BorderLayout.CENTER);
aFrame.setSize(300,200);
applet.init();
applet.start();
aFrame.setVisible(true);
}
}
初始界面
按下start计数从0不断增加
按下end计数停止
按下start按钮,创建SeparateSubTask对象,然后继续Counter2事件循环;此时会保存 SeparateSubTask的句柄,以便按下停止的时候能正常切换位于SeparateSubTask内部的
runFlag(运行标志)。随后那个线程便可启动
SeparateSubTask类是对Thread的一个简单扩展,它带有一个构造函数用来保存counter2的句柄,
然后通过start()来运行线程以及一个run(),由于SeparateSubTask知道自己容纳了指向Counter2的句柄,所以能够在需要的时候介入,并访问Counter2的TestField(文本字段)
这个程序如果不使用多线程,那点击start后停止就无法停下了,因为start后会无限循环调用sleep(),让end无法监听点击事件