Java的多线程机制

1.利用Thread的子类创建线程

例1.用Thread子类创建多线程程序。

先定义一个Thread的子类,该类的run方法只用来输出一些信息。

package thread;

public class myThread extends Thread{
    private static int count=0;
    
    public void run() {
        int i;
        for(i=0;i<100;i++){
            count=count+1;
            System.out.println("My name is "+getName()+" count="+count);
            try {
                sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public myThread(String name){
        super(name);
    }
    
}

下面用程序来创建线程对象并运行该线程对象。

package thread;

public class mulThread {

    public static void main(String[] args) {
        myThread trFirst,trSecond;
        trFirst = new myThread("First Thread");
        trSecond = new myThread("Second Thread");
        trFirst.start();
        trSecond.start();
        System.out.println("主线程结束!");
    }

}

2.实现Runnable接口创建线程

例2. 继承Runnable接口实现多线程。

package thread;

public class ThreadImRunable implements Runnable{
    private static int count=0;
    private Thread t;
    public void run() {
        int i;
        for(i=0;i<100;i++){
            count++;
            System.out.println("My name is "+t.getName()+" count="+count);
            try {
                t.sleep(10);
            } catch (Exception e) {
                // TODO: handle exception
            }
        }    
    }
    
    public ThreadImRunable(String name){
        t = new Thread(this,name);
    }
    
    public void start(){
        t.start();
    }
}

主程序跟前面相同。

package thread;

public class mulThread {

    public static void main(String[] args) {
        myThread trFirst,trSecond;
        trFirst = new myThread("First Thread");
        trSecond = new myThread("Second Thread");
        trFirst.start();
        trSecond.start();
        System.out.println("主线程结束!");
    }

}

3.使用isAlive()和join()等待子线程结束

例3. join()方法使用示例。

package thread;

public class demoJoin {
    public static void main(String[] args){
        myThread trFirst,trSecond;
        trFirst = new myThread("First Thread");
        trSecond = new myThread("Second Thread");
        try {
            trFirst.start();
            trSecond.start();
            trFirst.join();
            trSecond.join();
        } catch (InterruptedException e) {
            System.out.println("主线程被中断!");
        }
        System.out.println("主线程结束!");
    }
}

4.设置线程优先级

例4. 设置线程优先级示例。

package thread;

public class clicker extends Thread{
    private int click=0;
    private volatile boolean running=true;//volatile告诉编译器,不要自作主张为它编译优化
    public int getClick(){
        return click;
    }
    
    public void run() {
        while(running){
            click = click + 1;
        }
    }
    
    public void normalStop(){
        running = false;
    }
    
}

程序中的循环变量running被声明成volatile,这个关键字告诉编译器,不要自作主张为它进行编译优化。

注意:不要将循环体中“click=click+1”改成“++click”的形式。对于前者,编译器会生成多条命令,执行过程中系统有机会将它中断。而后者只有一条指令,系统不能将其中断,这样其他进程就难以有机会使用CPU。

package thread;

public class demoPri {

    public static void main(String[] args) {
        clicker c1High,c2Low;
        c1High=new clicker();
        c2Low=new clicker();
        c1High.setPriority(Thread.NORM_PRIORITY+2);
        c2Low.setPriority(Thread.NORM_PRIORITY-2);
        c2Low.start();
        c1High.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        
        c1High.normalStop();
        c2Low.normalStop();
        
        try {
            c1High.join();
            c2Low.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("c1High执行循环的次数为:"+c1High.getClick());
        System.out.println("c2Low 执行循环的次数为:"+c2Low.getClick());
    }

}

程序的输出结果为:

c1High执行循环的次数为:427835536
c2Low 执行循环的次数为:396647205

结果表明,优先级高的线程获得了更多的CPU运行时间。

5.线程的互斥

例5. 线程互斥示例。

package thread;

public class mutixThread extends Thread{
    private static int count = 0;
    private synchronized static void change(Thread t){
        count = count + 1;
        System.out.println("My name is "+t.getName()+" count="+count);
    }
    
    public void run() {
        int i;
        for(i=0;i<100;i++){
            change(this);
            try {
                sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    public mutixThread(String name){
        super(name);
    }
}

下面写一个程序测试它的运行情况。

package thread;

public class demoMutix {
    public static void main(String[] args){
        mutixThread t1,t2,t3;
        t1 = new mutixThread("First Thread");
        t2 = new mutixThread("Second Thread");
        t3 = new mutixThread("Third Thread");
        t1.start();
        t2.start();
        t3.start();
        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        System.out.println("主线程结束");
    }
}

程序运行结果如下:

.....
My name is Third Thread count=297
My name is First Thread count=298
My name is Third Thread count=299
My name is Second Thread count=300
主线程结束

6.线程的同步

例6. 线程同步示例。

package thread;

public class commSource {
    static boolean flag = true;
    static int data;
    static int count;
}
package thread;

public class setDataThread extends Thread {
    private readDataThread otherThread=null; //存储另外一个线程对象
    public void run(){
        for(int i=0;i<100;i++){
            if(!commSource.flag)
                try {
                    synchronized(this){ //锁定当前对象
                    wait(); //阻塞自己
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            commSource.flag = false;
            commSource.data = (int)(Math.random()*1000);
            commSource.count++;
            System.out.println("设置数据:"+commSource.data+" count="+commSource.count);
            synchronized(otherThread){ //锁定另外一个线程对象
                otherThread.notify();  //唤醒另外一个线程对象
            }
        }
    }
    public void setOtherThread(readDataThread rt){
        otherThread=rt;
    }
}
package thread;

public class readDataThread extends Thread{
    private setDataThread otherThread = null;
    public void run(){
        for(int i=0;i<100;i++){
            if(commSource.flag)
                try {
                    synchronized(this){
                        wait();
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            commSource.flag = true;
            System.out.println("获得数据:"+commSource.data);
            synchronized(otherThread){
                otherThread.notify();
            }
        }
    }
    public void setOtherThread(setDataThread st){
        otherThread = st;
    }
}
package thread;

public class demoSynchorny {

    public static void main(String[] args) {
        setDataThread str;
        readDataThread rtr;
        str=new setDataThread();
        rtr=new readDataThread();
        str.setOtherThread(rtr);
        rtr.setOtherThread(str);
        str.start();
        rtr.start();

    }

}

输出结果如下:

设置数据:295 count=1
获得数据:295
......
设置数据:974 count=99
获得数据:974
设置数据:526 count=100
获得数据:526

两个线程是严格交替运行的。

7.暂停恢复和停止线程

例7. 自己编写线程的暂停、恢复和停止方法。

package thread;

public class enhanceThread extends Thread {
    private static final int STOP = 1;
    private static final int RUNNING = 2;
    private static final int SUSPEND = 3;
    private int state = STOP;
    public synchronized void run(){
        int cnt = 0;
        while(state!=STOP){
            if(state==SUSPEND){
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            ++cnt;
            System.out.println("线程正在运行:"+cnt);
            try {
                sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    public void normalStop(){
        state = STOP;
    }
    
    public void normalSuspend(){
        state = SUSPEND;
    }
    
    //恢复线程运行
    public synchronized void normalResume(){
        state = RUNNING;
        notify();
    }
    
    public enhanceThread(){
        state = RUNNING;
    }
}
package thread;

public class demoEhanceThread {

    public static void main(String[] args) {
        enhanceThread tr;
        tr = new enhanceThread();
        System.out.println("启动线程!");
        tr.start();
        try {
            Thread.sleep(1000);
            System.out.println("将线程挂起!");
            tr.normalSuspend();
            Thread.sleep(1000);
            System.out.println("恢复线程运行!");
            tr.normalResume();
            Thread.sleep(1000);
            System.out.println("终止线程运行!");
            tr.normalStop();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

输出结果如下:

启动线程!
线程正在运行:1
线程正在运行:2
线程正在运行:3
线程正在运行:4
线程正在运行:5
线程正在运行:6
线程正在运行:7
线程正在运行:8
线程正在运行:9
线程正在运行:10
将线程挂起!
恢复线程运行!
线程正在运行:11
线程正在运行:12
线程正在运行:13
线程正在运行:14
线程正在运行:15
线程正在运行:16
线程正在运行:17
线程正在运行:18
线程正在运行:19
线程正在运行:20
终止线程运行!

8.生产者-消费者问题实例

例8. 生产者-消费者实例。

package thread;

public class common {
    private int production[]; //存放产品的缓冲区
    private int count;        //产品的实际数目
    private int BUFFERSIZE = 6; //缓冲区大小
    public common(){
        production = new int[BUFFERSIZE];
        count = 0;
    }
    //从缓冲区中取数据
    public synchronized int get(){
        int result;
        while(count<=0)
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        result = production[--count];
        notifyAll();
        return result;
    }
    //向缓冲区中写数据
    public synchronized void put(int newproduct){
        while(count>=BUFFERSIZE)
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        production[count++]=newproduct;
        notifyAll();
    }
}
package thread;
//消费者线程
public class consumer extends Thread {
    private common comm;
    public consumer(common mycomm){
        comm = mycomm;
    }
    
    public synchronized void run(){  //线程体
        int i,production;
        for(i=1;i<=20;i++){   //消费线程计数
            production = comm.get();
            System.out.println("得到的数据为:"+production);
            try {
                sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
package thread;
//生产者线程
public class producer extends Thread {
    private common comm;
    public producer(common mycomm){
        comm = mycomm;
    }
    
    public synchronized void run(){
        int i;
        for(i=1;i<=10;i++){
            comm.put(i);
            System.out.println("生产的数据为:"+i);
            try {
                sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
package thread;

public class producer_consumer {
    public static void main(String[] args){
        common comm = new common();
        producer p1 = new producer(comm);
        producer p2 = new producer(comm);
        consumer c1 = new consumer(comm);
        p1.start();
        p2.start();
        c1.start();
    }
}

程序某次运行结果如下:

生产的数据为:1
得到的数据为:1
生产的数据为:1
得到的数据为:2
生产的数据为:2
生产的数据为:2
生产的数据为:3
得到的数据为:3
生产的数据为:3
生产的数据为:4
得到的数据为:4
生产的数据为:4
生产的数据为:5
得到的数据为:5
生产的数据为:5
得到的数据为:5
生产的数据为:6
生产的数据为:6
得到的数据为:6
生产的数据为:7
生产的数据为:8
得到的数据为:7
得到的数据为:8
生产的数据为:9
生产的数据为:10
得到的数据为:9
得到的数据为:10
生产的数据为:7
得到的数据为:7
生产的数据为:8
得到的数据为:8
生产的数据为:9
得到的数据为:9
生产的数据为:10
得到的数据为:10
得到的数据为:6
得到的数据为:4
得到的数据为:3
得到的数据为:2
得到的数据为:1

结果表明,该程序已经很好地解决了生产者线程和消费者线程间的同步问题。

原文地址:https://www.cnblogs.com/gaopeng527/p/4234211.html