Demo

多线程学习笔记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无法监听点击事件

原文地址:https://www.cnblogs.com/kongw/p/13886923.html