【问题标题】:Multiple Consumer Producer In JavaJava中的多个消费者生产者
【发布时间】:2019-02-04 13:55:34
【问题描述】:

我尝试为消费者创建 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();
            }
        }

        @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 >>>>");
    }
}

程序的输出

线程 2>>> 产生 >> 0

Thread-1 >>> 消费 >>>0

线程 3>>> 产生 >> 0

线程“Thread-0”java.lang.IndexOutOfBoundsException 中的异常: 索引:0,大小:0 在 java.util.ArrayList.rangeCheck(ArrayList.java:657) 在 java.util.ArrayList.remove(ArrayList.java:496) 在 com.threading.TestConsumerProducer2$Consumer.consume(TestConsumerProducer2.java:27) 在 com.threading.TestConsumerProducer2$Consumer.run(TestConsumerProducer2.java:35) 在 java.lang.Thread.run(Thread.java:748) Thread-2>>> 产生 >> 1

Thread-1 >>> 消费 >>>0

线程 3>>> 产生 >> 1

线程 1 >>> 消耗 >>>1

线程 2>>> 产生 >> 2

线程 1 >>> 消耗 >>>1

线程 3>>> 产生 >> 2

线程 1 >>> 消耗 >>>2

线程 2>>> 产生 >> 3

线程 1 >>> 消耗 >>>2

线程 2>>> 产生 >> 4

线程 3>>> 产生 >> 3

线程 1 >>> 消耗 >>>3

线程 2>>> 产生 >> 5

线程 1 >>> 消耗 >>>4

线程 3>>> 产生 >> 4

Thread-1 >>> 消费 >>>3

Thread-2>>> 生产 >> 6 Thread-1 >>>> 消费 >>>5

线程 2>>> 产生 >> 7

线程 3>>> 产生 >> 5

问题陈述: 为什么没有一个线程执行 10 次? 代码中的死锁情况在哪里? 当 Goods 对象被消费者线程锁定并且如果 size

【问题讨论】:

  • 您标记的前面是生产者-消费者问题中的一种基本问题。在这里,我试图使用更多的线程来实现相同的逻辑,但更复杂。所以在上一个问题中分配了两个线程来执行这两个操作,所以每个线程对每个操作都进行了分配,但是在这里为每个操作分配了两个线程。

标签: java multithreading producer-consumer


【解决方案1】:

将代码中出现的if 更改为while 可以解决问题。

Guarded Blocks tutorial on Oracle's site 中有相关建议:

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

(中断意味着从等待中返回,不一定是源自调用 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 >>>>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多