Java多线程9 多线程的提高

之前的内容:理解多线程。创建多线程。多线程的安全问题/分析与理解。安全问题的解决办法/锁

———————————多线程的提高    线程之间的通信—————————————

之前的例子都是多个线程执行一个线程任务,多线程的提高——多个线程执行不同的线程任务,并发执行

例如:消费者与生产者,一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行

这叫做线程间的通信——你有你的动作,我有我的动作,但是处理的是同一个资源

初步代码:(执行有错误)

package Thread;
/*
线程的提升;生产者消费者问题
一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行
//线程间的通信
简化后的生产者和消费者——生产一个 消费一个
1.描述资源
2.描述生产者,具备自己的任务
3.描述消费者,具备自己的任务
 */
//描述资源——属性:名字,编号。行为:对商品名称赋值,获取商品
class Resource{//简化程序-设资源只有一个
    private String name;
    private int number=1;
    //提供设置方法
    public void set(String name ){
        //给成员变量赋值
        this.name = name+number;
        number++;
        //打印生产了那个商品
        System.out.println(Thread.currentThread().getName()+"    生产者    "+this.name);
    }
    //消费者的
    public void Out(){
        System.out.println(Thread.currentThread().getName()+"   消费者    "+this.name);
    }
}
class Producer implements Runnable{
    private Resource  r;
    Producer(Resource r){
        this.r = r;
    }
    public void run(){
        r.set("面包");
    }
}
//描述消费者
class consumer implements Runnable{
    private Resource r;
    consumer(Resource r){
        this.r=r;
    }
    public void run(){
        r.Out();
    }
}
public class producerAndConsumer {
    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();
    }
}

运行结果:有错误

加上一个小循环:

问题:这个程序的输出必须遵守,生产一个消费一个,正确的数据应该为:1 1 2 2 3 3 4 4 5 5.

————————————————解决问题/分析问题—————————————

以上两种错误情况是其中的两种,现在针对相应的错误做出解决方案:

1.很早被生产的商品(编号已经)被覆盖,才被消费到

输出结果:1 2 3 4 5 6(生产者)//1 .。。。(消费者)

按理说编号1 早已经被覆盖,不应该现在才被消费到

解决办法《这是线程的安全问题——使用同步   ——————解决了该问题

2.问题1 解决,但是又出现新的问题:有些商品不会被消费到(连续生产但是没有消费/对同一个商品进行多次消费):1 2 3 4 5 //(生产者)5 5 5 5//(消费者)

我们的希望应该是:生产一个消费一个

思考:什么时候生产————————盘子里没有商品时

什么时候消费————————————盘子里有商品时

设置标记

思路

正确的代码:

package Thread;
/*
线程的提升;生产者消费者问题
一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行
//线程间的通信
简化后的生产者和消费者——生产一个 消费一个
1.描述资源
2.描述生产者,具备自己的任务
3.描述消费者,具备自己的任务
 */
//描述资源——属性:名字,编号。行为:对商品名称赋值,获取商品
class Resource{//简化程序-设资源只有一个
    private String name;
    private int number=1;
    private boolean flag;
    //提供设置方法
    public synchronized void set(String name ){
        if(flag){//先判断
            try{wait();}catch(InterruptedException e){}//存在商品,此线程停止
        }
        else {
            //给成员变量赋值
            this.name = name + number;
            number++;
            //打印生产了那个商品
            System.out.println(Thread.currentThread().getName() + "    生产者    " + this.name);
            flag = true;//生产完,修改标志
            notify();//唤醒消费者
        }
    }
    //消费者的
    public synchronized void Out(){
        if(!flag){//先判断
            try{wait();}catch(InterruptedException 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(){
        for(int x=0;x<5;x++) {
            r.set("面包");
        }
    }
}
//描述消费者
class consumer implements Runnable{
    private Resource r;
    consumer(Resource r){
        this.r=r;
    }
    public void run(){
        for(int x=0;x<5;x++) {
            r.Out();
        }
    }
}
public class producerAndConsumer {
    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();
    }
}

总结:1.关于线程的提升——————线程间的的通信。其实有一点想的单例设计模式的需求和环境,但是单例设计的对象是强制唯一的,线程间的通信在此的要求没那么的苛刻,从代码上也能找到异同

2.关于等待和唤醒机制

猜你喜欢

转载自blog.csdn.net/Stitch__/article/details/81639656