天天看点

java基础12:线程间通信----等待唤醒机制

 今天学习了等待唤醒机制,通过一个例子做个小小的总结。

需求是对某个数据进行修改和输出操作,要求两个操作同时进行,且先修改后输出。

设计思路:1,需要一个公共数据类。两个线程,一个Input、一个Output。

                    2,Input和Output应该是两个线程,这样才能同时进行。

                    3,Input和Output的对数据进行修改的方法应该实现同步,以解决线程安全问题。

                    4,需要有等待唤醒机制,这样才能实现先修改后输出。

实现代码:

//共享资源类,name和sex是被修改的数据,flag作为数据被修改之后的标识。

class Res{

    String name;

    String sex;

    boolean flag=false;

}

class Input implements Runnable{

    private Res r;

    Input(Res r){

        this.r=r;

    }

    public void run(){

        int x=0;

        while(true){

            synchronized(r){

                if(r.flag){//如果数据被修改过,那么写线程wait(),等待读线程完成后唤醒。

                    try {

                        r.wait();

                    } catch (InterruptedException e) {

                        // TODO Auto-generated catch block

                        e.printStackTrace();

                    }

                }

                if(x==0){

                r.name="Mike";

                r.sex="Man";

                }else{

                r.name="丽丽";

                r.sex="女";

                }

                r.flag=true;//完成写操作后,将标志位改为true,表示写线程完成,唤醒其他线程。

                r.notify();

            }

            x=(x+1)%2;

        }

    }

}

class Output implements Runnable{

    private Res r;

    Output(Res r){

        this.r=r;

    }

    public void run(){

        while(true){

            synchronized(r){

                if(!r.flag){//如果标志位为false,说明读线程完成,必须等待写线程操作。

                    try{

                        r.wait();

                    }catch(InterruptedException e){

                        e.printStackTrace();

                    }

                }

                System.out.println(r.name+"::"+r.sex);

                r.flag=false;//读完之后将标志位改为false,表示读完,并唤醒写线程。

                r.notify();

            }

        }

    }

}

public class ThreadComm {

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        Res r=new Res();

        Input in=new Input(r);

        Output ou=new Output(r);

        Thread t1=new Thread(in);

        Thread t2=new Thread(ou);

        t1.start();

        t2.start();

    }

}

class Res2{

    private String name;

    private String sex;

    boolean flag=false;

    public synchronized void set(String name,String sex){

        if(flag){

            try{

                this.wait();

            }catch(Exception e){

                e.printStackTrace();

            }

        }    

        this.name=name;

        this.sex=sex;

        flag=true;

        this.notify();

    }

    public synchronized void get(){

        if(!flag){

            try{

                this.wait();

            }catch(Exception e){

                e.printStackTrace();

            }

        }

        System.out.println(name+"::"+sex);

        flag=false;

        this.notify();

    }

}

class Input2 implements Runnable{

    private Res2 r;

    Input2(Res2 r){

        this.r=r;

    }

    public void run(){

        int x=0;

        while(true){

            if(x==0){

                r.set("Mick", "Man");

            }else{

                r.set("丽丽", "女女女女");

            }

            x=(x+1)%2;

        }

    }

}

class Output2 implements Runnable{

    private Res2 r;

    Output2(Res2 r){

        this.r=r;

    }

    public void run(){

        while(true){

            r.get();

        }

    }

}

public class WaNoYouDemo {

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        Res2 r=new Res2();

        new Thread(new Input2(r)).start();

        new Thread(new Output2(r)).start();

    }

}