1.多线程-线程间通信-问题演示

    多线程间通信:多个线程处理同一资源,但是处理动作却不同。

 

//创建一个资源描述。资源中有name sex。用于存储数据。
class Resource{
    String name;
    String sex;
}

//需要定义一个输入任务描述。既然是线程任务,必须实现Runnable接口。 
class Input implements Runnable{
    private Resource r;
    Input(Resource r){
        this.r = r;
    }
    //覆盖run方法。 
    public void run(){
        int x = 0;
        while(true){
         //输入任务中必然要处理资源。要给资源中的name sex赋值。
         //需要对象。对象确定吗?不确定,传递进来就哦了。输入任务一创建对象就必须有资源。
         //完全可以在构造时明确资源对象。 
            if(x==0){
                r.name = "zhangsan";
                r.sex = "man";
            }else{
                r.name = "小花";
                r.sex = "女女女女女";
            }
            //赋值后,将标记改为true,说明有值。
            x = (x+1)%2;
        }
    }
}
 
//需要定义一个输出任务描述。既然是线程任务,必须实现Runnable接口。 
class Output implements Runnable{
    private Resource r;
    Output(Resource r){
        this.r = r;
    }
    public void run(){
        while(true){
            System.out.println(r.name+"...."+r.sex);
        }
    }
}

  

class  ThreadDemo_Resource{
    public static void main(String[] args) {
        //1,创建资源的对象。
        Resource r = new Resource();
        //2,创建任务对象。
        Input in = new Input(r);
        Output out = new Output(r);
         
        //3,创建线程对象。
        Thread t1 = new Thread(in);
        Thread t2 = new Thread(out);
        //4,启动并运行线程。
        t1.start();
        t2.start();
    }
}


运行结果:

wKioL1c3KHWwP8BJAAAT8ii36XQ386.png


2.多线程-线程间通信-问题解决

使用同步代码块

class Resource{
    String name;
    String sex;
}

class Input implements Runnable{
    private Resource r;
    Input(Resource r){
        this.r = r;
    }
     
    public void run(){
        int x = 0;
        while(true){
            synchronized(r){        
                if(x==0){
                    r.name = "zhangsan";
                    r.sex = "man";
                }else{
                    r.name = "小花";
                    r.sex = "女女女女女";
                }
            }
            x = (x+1)%2;  
        }
    }
}
 

class Output implements Runnable{
    private Resource r;
    Output(Resource r){
        this.r = r;
    }
    public void run(){
        while(true){
            synchronized(r){
                System.out.println(r.name+"...."+r.sex);
            }
        }
    }
}

  

class  ThreadDemo_Resource{
    public static void main(String[] args) {
        //1,创建资源的对象。
        Resource r = new Resource();
        //2,创建任务对象。
        Input in = new Input(r);
        Output out = new Output(r);
         
        //3,创建线程对象。
        Thread t1 = new Thread(in);
        Thread t2 = new Thread(out);
        //4,启动并运行线程。
        t1.start();
        t2.start();
    }
}



3.多线程-线程间通信-等待唤醒机制

wait():可以让当前处于等待,这时的线程被临时存储到的线程池中。

notify():唤醒线程池中任意一个等待的线程。

notifyAll():唤醒线程池中所有的等待线程。


这些方法在使用时,必须要定义在同步中,必须被所属同步的锁对象来调用。

 

 

//创建一个资源描述。资源中有name sex。用于存储数据。
class Resource{
    String name;
    String sex;
    //定义标记,用于判断资源中是否有数据。
    boolean flag;//默认值为false
}
 
 
//需要定义一个输入任务描述。
class Input implements Runnable{
    private Resource r;
    Input(Resource r){
        this.r = r;
    }
    
    public void run(){
        int x = 0;
        while(true){
            synchronized(r){ 
                if(r.flag){//flag为false不执行wait语句
                    try{r.wait();}catch(Exception e){}}
                if(x==0){
                    r.name = "zhangsan";
                    r.sex = "man";
                }else{
                    r.name = "小花";
                    r.sex = "女女女女女";
                }
                //赋值后,将标记改为true,说明有值啦。
                r.flag = true;
                //唤醒等待的线程。
                r.notify();
            }
            x = (x+1)%2; 
        }
    }
}
 
//需要定义一个输出任务描述。 
class Output implements Runnable{
    private Resource r;
        Output(Resource r){
        this.r = r;
    }
    public void run(){
        while(true){
            synchronized(r){
                if(!r.flag){//资源中没有数据就等待。
                    try{r.wait();}catch(Exception e){}}
                System.out.println(r.name+"...."+r.sex);
                //将标记改为false.
                r.flag = false;
                r.notify();//唤醒等待的线程。其实就是唤醒了输入线程。 
            }
        }
    }
}
 
 
class  ThreadDemo_Resource{
    public static void main(String[] args) {
        //1,创建资源的对象。
        Resource r = new Resource();
        //2,创建任务对象。
        Input in = new Input(r);
        Output out = new Output(r);
         
        //3,创建线程对象。
        Thread t1 = new Thread(in);
        Thread t2 = new Thread(out);
        //4,启动并运行线程。
        t1.start();
        t2.start();
    }
}

运行结果

wKiom1c3K6XhiF0OAAAeVu-xMss787.png


4.多线程-线程间通信-代码优化

//资源描述
class Resource{
    private String name;
    private String sex;
    //定义标记,用于判断资源中是否有数据。
    private boolean flag;
     
    //对外提供方法访问这些属性。
    public synchronized void set(String name,String sex){
        if(flag)//flag为false,输入任务不等待
            try{this.wait();}catch(Exception e){}
         
        this.name = name;
        this.sex = sex;
        flag = true;
        this.notify();
    }
     
    //对外提供获取方法。
    public synchronized void out(){
        if(!flag)//falg为false,输出任务等待
            try{this.wait();}catch(Exception e){}
        System.out.println(name+"::::"+sex);
        flag = false;
        this.notify();
    }
}
 
 
//需要定义一个输入任务描述。 
    class Input implements Runnable{
        private Resource r;
        Input(Resource r){
            this.r = r;
        }
        //覆盖run方法。 
        public void run(){
            int x = 0;
            while(true){
                if(x==0){
                    r.set("zhangsan","man");
                }else{
                    r.set("小花","女女女女女");
                }
                x = (x+1)%2;
            }
        }
    }

 
//需要定义一个输出任务描述。 
class Output implements Runnable{
    private Resource r;
    Output(Resource r){
        this.r = r;
    }
    public void run(){
        while(true){
            r.out();
        }
    }
}
 
 
 
class  ThreadDemo2_Resource{
    public static void main(String[] args) {
        //1,创建资源的对象。
        Resource r = new Resource();
        //2,创建任务对象。
        Input in = new Input(r);
        Output out = new Output(r);
         
        //3,创建线程对象。
        Thread t1 = new Thread(in);
        Thread t2 = new Thread(out);
        //4,启动并运行线程。
        t1.start();
        t2.start();
    }
}


 

5.多线程-线程间通信-单生产者单消费者示例

/*
单生产者和单消费者。等待唤醒机制。
*/
//资源
class Resource{
    private String name;//定义一个商品都有名字。
    private int count = 1;//定义一个商品的编号。
    private boolean flag = false;//定义用来判断是否有商品的标记。
    
    public synchronized  void set(String name){
        if(flag)//flag为false,生成任务不等待
            try{wait();}catch(Exception e){}
        this.name = name+"--"+count;
        count++;
        System.out.println(Thread.currentThread().getName()+"---生产了,"+this.name);
        
        flag = true;//将标记改为true。
        notify();//唤醒等待的线程。 
    }
     
    public synchronized void get(){
        if(!flag)//flag为false,消费任务等待
            try{wait();}catch(Exception e){}
        System.out.println(Thread.currentThread().getName()+"-------消费了....."+this.name);
        flag = false;
        notify();
    }
}
 
 
//定义生产者的任务。
class Producer implements Runnable{
    private Resource r;
    Producer(Resource r){
        this.r = r;
    }
    public void run(){
        while(true){
            r.set("蛋糕");
        }
    } 
}
 
 
//定义消费者的任务。
class Consumer implements Runnable{
    private Resource r;
    Consumer(Resource r){
        this.r = r;
    }
    public void run(){
        while(true){
            r.get();
        }
    }
}
 
 
class ThreadDemo_Producer_Consumer {
    public static void main(String[] args) {
        Resource r = new Resource();
        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(con);
        t1.start();
        t2.start();
    }
}


单生产单消费,等待和唤醒的始终只有一个线程,没有问题。

wKiom1c3L6TQlaR2AABCgYC_chg003.png