为了账号安全,请及时绑定邮箱和手机立即绑定

Java中的多个消费者生产者

Java中的多个消费者生产者

慕哥9229398 2021-08-19 19:17:55
我尝试为消费者创建 2 个线程,为生产者创建 2 个线程。所有 4 个线程都在与一种资源竞争。其中两个试图从资源中消费,其中两个试图生产。下面是代码package com.threading;import java.util.ArrayList;import java.util.List;public class TestConsumerProducer2 {    protected static int maxSize = 2;    static class Consumer implements Runnable {        List<Integer> goods;        public Consumer(List<Integer> goods) {            this.goods = goods;        }        public void consume() {            synchronized (goods) {                if (goods.size() <= 0) {                    try {                        goods.wait();                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                System.out.println(Thread.currentThread().getName() + " >>>> consuming >>>" + goods.remove(0));                goods.notifyAll();            }        }        @Override        public void run() {            for (int i = 0; i < 10; i++) {                consume();                try {                    Thread.currentThread().sleep(100);                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }    }    static class Producer implements Runnable {        List<Integer> goods;        public Producer(List<Integer> goods) {            this.goods = goods;        }        public void produce(int i) {            synchronized (goods) {                if (goods.size() >= maxSize) {                    try {                        goods.wait();                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                System.out.println(Thread.currentThread().getName() + ">>> producing >> " + i);                goods.add(i);                goods.notifyAll();            }        }
查看完整描述

1 回答

?
千巷猫影

TA贡献1829条经验 获得超7个赞

更改代码中出现的iftowhile可以解决问题。


Oracle 网站上的Guarded Blocks 教程中有相关建议,其中说:


注意:始终在测试等待条件的循环内调用 wait。不要假设中断是针对您正在等待的特定条件,或者条件仍然为真。


(中断是指从等待中返回,不一定是来自调用 Thread.interrupt 的人的实际中断。)


关键点:


只有当线程在检查时持有锁时,它才知道货物列表的内容。


调用 wait 会放弃锁,允许其他线程在这个线程处于休眠状态时取得进展。


一旦线程放弃锁,它之前对货物列表状态所做的任何检查都不再有效。


一旦线程从等待中返回,它就重新获得了锁,但该线程需要重新评估条件检查,否则它正在处理陈旧的信息。在线程上次检查条件的时间和当前时间之间可能发生了很多事情。您得到 IllegalArgumentException 是因为当前线程假设在当前线程等待时另一个线程删除了某些东西。


package com.threading;


import java.util.ArrayList; 


import java.util.List;


public class TestConsumerProducer2 {


protected static int maxSize = 2;


static class Consumer implements Runnable {

    List<Integer> goods;


    public Consumer(List<Integer> goods) {

        this.goods = goods;

    }


    public void consume() {

        synchronized (goods) {


            while (goods.size() <= 0) {

                try {

                    goods.wait();

                } catch (InterruptedException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                }

            }

            System.out.println(Thread.currentThread().getName() + " >>>> consuming >>>" + goods.remove(0));

            goods.notifyAll();

        }

    }


    @Override

    public void run() {

        for (int i = 0; i < 10; i++) {

            consume();

            try {

                Thread.currentThread().sleep(100);

            } catch (InterruptedException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

    }

}


static class Producer implements Runnable {

    List<Integer> goods;


    public Producer(List<Integer> goods) {

        this.goods = goods;

    }


    public void produce(int i) {

        synchronized (goods) {


            while (goods.size() >= maxSize) {

                try {

                    goods.wait();

                } catch (InterruptedException e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                }

            }

            System.out.println(Thread.currentThread().getName() + ">>> producing >> " + i);

            goods.add(i);

            goods.notifyAll();

        }

    }


    @Override

    public void run() {

        // TODO Auto-generated method stub

        for (int i = 0; i < 10; i++) {

            produce(i);

            try {

                Thread.currentThread().sleep(100);

            } catch (InterruptedException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

    }

}


public static void main(String[] args) {

    List<Integer> goods = new ArrayList<>();

    Consumer consumer = new Consumer(goods);

    Producer producer = new Producer(goods);

    Thread consumerWorker1 = new Thread(consumer);

    Thread consumerWorker2 = new Thread(consumer);


    Thread prroducerWorker1 = new Thread(producer);

    Thread prroducerWorker2 = new Thread(producer);


    consumerWorker1.start();

    consumerWorker2.start();

    prroducerWorker1.start();

    prroducerWorker2.start();


    try {

        consumerWorker1.join();

        consumerWorker2.join();

        prroducerWorker1.join();

        prroducerWorker2.join();

    } catch (InterruptedException e) {

        // TODO Auto-generated catch block

        e.printStackTrace();

    }


    System.out.println("Job completed >>>>");

}


}

代码现在成功完成,输出如下:


C:\>java com.threading.TestConsumerProducer2

Thread-2>>> producing >> 0

Thread-1 >>>> consuming >>>0

Thread-3>>> producing >> 0

Thread-0 >>>> consuming >>>0

Thread-2>>> producing >> 1

Thread-3>>> producing >> 1

Thread-0 >>>> consuming >>>1

Thread-1 >>>> consuming >>>1

Thread-2>>> producing >> 2

Thread-3>>> producing >> 2

Thread-0 >>>> consuming >>>2

Thread-1 >>>> consuming >>>2

Thread-2>>> producing >> 3

Thread-0 >>>> consuming >>>3

Thread-3>>> producing >> 3

Thread-1 >>>> consuming >>>3

Thread-2>>> producing >> 4

Thread-0 >>>> consuming >>>4

Thread-3>>> producing >> 4

Thread-1 >>>> consuming >>>4

Thread-2>>> producing >> 5

Thread-0 >>>> consuming >>>5

Thread-3>>> producing >> 5

Thread-1 >>>> consuming >>>5

Thread-2>>> producing >> 6

Thread-0 >>>> consuming >>>6

Thread-3>>> producing >> 6

Thread-1 >>>> consuming >>>6

Thread-2>>> producing >> 7

Thread-0 >>>> consuming >>>7

Thread-3>>> producing >> 7

Thread-1 >>>> consuming >>>7

Thread-2>>> producing >> 8

Thread-0 >>>> consuming >>>8

Thread-3>>> producing >> 8

Thread-1 >>>> consuming >>>8

Thread-2>>> producing >> 9

Thread-0 >>>> consuming >>>9

Thread-3>>> producing >> 9

Thread-1 >>>> consuming >>>9

Job completed >>>>


查看完整回答
反对 回复 2021-08-19
  • 1 回答
  • 0 关注
  • 207 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信