自学内容网 自学内容网

【Java笔记】6-三个线程交替打印数字(生产者消费者Plus版)

生产者消费者问题是老生常谈的问题,考察线程的同步等知识
Java中用于实现生产者消费者主要使用synchronized、对象.wait()、对象.notify()来实现

前置知识

synchronized

该字段可对方法使用、可对代码片使用,用于控制线程互斥

wait()

用于通知掌握该对象锁的线程等待通知

notify()

用于通知等待对象锁的线程开始运行

生产者消费者

其中list是生产者消费者共享的资源
每次该共享资源被释放(生产完或消费完),生产者消费者都有可能进入临界区,但无所谓,不满足条件的会卡住,让另一个执行

public class ProduceConsume {
    public static void main(String[] args) {
        List list =new ArrayList();
        Producer p=new Producer(list);
        Consumer c=new Consumer(list);
        new Thread(p,"生产者").start();
        new Thread(c,"消费者").start();
    }
}

class Producer implements Runnable {
    private List list;
    public Producer(List list) {
        this.list = list;
    }
    public void run(){
        while(true){
            synchronized (list) {//synchronized控制不同线程同步
                if (list.size()>0){
                    //如果发现不能生产 就调用wait(),释放锁
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }else{
                //否则就生产一个,并通知消费者可以来拿
                //就算下次又是生产者进来,那无所谓,会进入wait
                    produce();
                    list.notifyAll();
                }
            }
        }
    }
    public void produce(){
        list.add(new Object());//加到后面
        System.out.println(Thread.currentThread().getName()+"生产产品");
    }
}
class Consumer implements Runnable {
    private List list;
    public Consumer(List list) {
        this.list = list;
    }
    public void run(){
        while (true){
            synchronized (list) {
                if (list.size()==0){
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }else{
                    consume();
                    list.notifyAll();
                }
            }
        }
    }
    public void consume(){
        list.remove(0);
        System.out.println(Thread.currentThread().getName()+"消费产品");
    }
}

三个线程交替打印数字

这里思想非常简单,在生产者消费者的基础上,有以下变化:

  1. 共享资源变成三个,两两使用一个控制同步
  2. 每个线程消费后再生产,这样下一个线程可以消费再生产
  3. 两层synchronized嵌套,第一层控制消费,第二层控制生产
  4. main函数里初始化往第一个共享资源生产一下,使得整体开始运行
  5. 三个线程共享代码段,只是传入的参数不同
import java.util.ArrayList;
import java.util.List;

public class PrintInTurn {
    public static void main(String[] args) {
        List list1 = new ArrayList();
        List list2 = new ArrayList();
        List list3 = new ArrayList();
        list1.add(new Object());
        ProducerConsumer p1=new ProducerConsumer(list1,list2);
        ProducerConsumer p2=new ProducerConsumer(list2,list3);
        ProducerConsumer p3=new ProducerConsumer(list3,list1);
        new Thread(p1,"p1").start();
        new Thread(p2,"p2").start();
        new Thread(p3,"p3").start();
    }
}

class ProducerConsumer implements Runnable {
    private List list1,list2;
    public ProducerConsumer(List list1, List list2) {
        this.list1 = list1;
        this.list2 = list2;
    }
    public void run(){
        //int i=0;//控制生产个数
        while(true){
            //if (i>2){//控制生产个数
            //    break;
            //}
            synchronized (list1) {
                if (list1.size()==0){
                    //线程进入等待
                    try {
                        list1.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }else{
                    consume(list1);
                    //i++;//控制生产个数
                    list1.notifyAll();
                    synchronized (list2) {
                        if (list2.size()==1){
                            try {
                                list2.wait();
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                        }else{
                            produce(list2);
                            list2.notifyAll();
                        }
                    }
                }
            }
        }
    }
    public void produce(List lis){
        lis.add(new Object());//加到后面
        System.out.println(Thread.currentThread().getName()+"生产产品");
    }
    public void consume(List lis){
        lis.remove(0);
//        System.out.println(Thread.currentThread().getName()+"消费产品");
    }
}

原文地址:https://blog.csdn.net/weixin_43735161/article/details/143490320

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!