生产者/消费者模型使用Java(同步),但始终运行相同的线程

生产者/消费者模型使用Java(同步),但始终运行相同的线程,java,multithreading,Java,Multithreading,一切看起来都很好,但当我跑步时,结果是: 开始线程(1):Pro2 开始线程(2):Pro1 起始线程(1):Con1 起始线程(2):Con2 项目2生产:EWlmJdi2KK 左: 项目2:EWlmJdi2KK ---左:1--- Con2消耗量:EWlmJdi2KK 左: ---左:0--- Pro2产品:Nx7QPyG7vs 左: 项目2:Nx7QPyG7vs ---左:1-- 项目2生产:xl85Zwr80a 左:Pro2:Nx7QPyG7vs 项目2:xl85Zwr80a ---左:

一切看起来都很好,但当我跑步时,结果是:

开始线程(1):Pro2

开始线程(2):Pro1

起始线程(1):Con1

起始线程(2):Con2

项目2生产:EWlmJdi2KK

左:

项目2:EWlmJdi2KK

---左:1---

Con2消耗量:EWlmJdi2KK

左:

---左:0---

Pro2产品:Nx7QPyG7vs

左:

项目2:Nx7QPyG7vs

---左:1--

项目2生产:xl85Zwr80a

左:Pro2:Nx7QPyG7vs 项目2:xl85Zwr80a

---左:2---

在运行时始终是同一个生产者和消费者

这是我的密码: Main.java:

package com.producer;

import org.apache.commons.lang3.RandomStringUtils;

public class Main {

    public static void main(String[] args) {
        ThreadSynchronized semaphore = new ThreadSynchronized();
        ThreadSynchronized.Producer pro = semaphore.new Producer("1");
        ThreadSynchronized.Consumer con = semaphore.new Consumer("2");
        new Thread(pro, "Pro2").start();
        new Thread(pro, "Pro1").start();
        new Thread(con, "Con1").start();
        new Thread(con, "Con2").start();

    }
}
ThreadSynchronized.java:

package com.producer;

import java.util.LinkedList;

/**
 * Created by SkyAo on 15/10/18.
 */
public class ThreadSynchronized {
    private static int pid;
    private static int cid;
    public LinkedList<Item> items = new LinkedList<>();
    private Item temp;
    private int item;
    private boolean flag = false;

    class Producer implements Runnable {
        private String name;
        private int id;

        public Producer(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            this.id = ++pid;
            System.out.println("Start Thread(" + this.id + "): " + Thread.currentThread().getName());
            while (true)
                this.produce();
        }

        private synchronized void produce() {
            try {

                Thread.sleep((int)(Math.random()*5000)+3000);
                if (items.size() < 5) {
                    items.add(new Item(this.id, Thread.currentThread().getName()));
                    temp = items.getLast();
                    System.out.println(temp.sourceName + " Produce: " + temp.semi);

                    System.out.println("Left: ");

                    for (Item item : items) {
                        System.out.println(item.sourceName + ":" + item.semi);
                    }

                    System.out.println("---Left: " + items.size() + "---");
                } else {
                    super.wait();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                super.notifyAll();
            }

        }


    }

    class Consumer implements Runnable {
        private String name;
        private int id;

        public Consumer(String name) {
            this.name = name;
            //this.id = ++cid;
        }

        @Override
        public void run() {
            this.id = ++cid;
            System.out.println("Start Thread(" + this.id + "): " + Thread.currentThread().getName());
            while (true)
                this.consume();

        }

        private synchronized void consume() {
            try {
                Thread.sleep((int) (Math.random() * 5000) + 3000);
                if (items.size() > 0) {
                    temp = items.removeFirst();
                    System.out.println(Thread.currentThread().getName() + " Consume: " + temp.semi);
                    System.out.println("Left: ");

                    for (Item item : items) {
                        System.out.println(item.sourceName + ":" + item.semi);
                    }

                    System.out.println("---Left: " + items.size() + "---");
                } else {
                    super.wait();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                super.notifyAll();
            }
        }
    }
}
package.com.producer;
导入java.util.LinkedList;
/**
*由SkyAo于2018年10月15日创建。
*/
公共类线程同步{
私有静态int-pid;
私有静态int-cid;
public LinkedList items=new LinkedList();
私人物品温度;
私人物品;
私有布尔标志=false;
类生成器实现了Runnable{
私有字符串名称;
私有int-id;
公共生产者(字符串名称){
this.name=名称;
}
@凌驾
公开募捐{
this.id=++pid;
System.out.println(“开始线程(“+this.id+”):“+Thread.currentThread().getName());
while(true)
这个;
}
私有同步void product(){
试一试{
Thread.sleep((int)(Math.random()*5000)+3000);
如果(items.size()<5){
添加(新项(this.id,Thread.currentThread().getName());
temp=items.getLast();
系统输出打印项次(temp.sourceName+“product:”+temp.semi);
System.out.println(“左:”);
用于(项目:项目){
System.out.println(item.sourceName+“:”+item.semi);
}
System.out.println(“----左:“+items.size()+”--”);
}否则{
超级。等等();
}
}捕获(例外e){
e、 printStackTrace();
}最后{
super.notifyAll();
}
}
}
类使用者实现Runnable{
私有字符串名称;
私有int-id;
公共使用者(字符串名称){
this.name=名称;
//this.id=++cid;
}
@凌驾
公开募捐{
this.id=++cid;
System.out.println(“开始线程(“+this.id+”):“+Thread.currentThread().getName());
while(true)
这个。消费();
}
私有同步的void消费(){
试一试{
Thread.sleep((int)(Math.random()*5000)+3000);
如果(items.size()>0){
temp=items.removeFirst();
System.out.println(Thread.currentThread().getName()+“Consume:”+temp.semi);
System.out.println(“左:”);
用于(项目:项目){
System.out.println(item.sourceName+“:”+item.semi);
}
System.out.println(“----左:“+items.size()+”--”);
}否则{
超级。等等();
}
}捕获(例外e){
e、 printStackTrace();
}最后{
super.notifyAll();
}
}
}
}

我不知道发生了什么以及如何修复它,谢谢你的帮助。

你正在用Java的方式解决一个棘手的设计问题。这种方法容易出错,而且不可靠。我建议使用现成的解决方案。不过,对于您的情况,我认为您会发现这很有帮助。

使用notify/wait解决生产者/消费者问题很棘手。我的建议是你调查一下“排队”。更具体地说,是的一个子类

首先创建一个合适的队列。然后创建生产者对象。每个生产者对象实现
Runnable
。创建对象时,将队列作为参数传递。您可以将生产者对象作为新线程启动

您对消费者对象也执行相同的操作。它们还实现了
Runnable
,并在创建时作为参数传递给队列。当所有生产者和消费者线程都在运行时,您的主程序就完成了

它是传递给所有生产者和消费者线程的同一队列对象。同步由队列处理

生产者对象中的代码写入队列或在队列上放置条目,而使用者中的代码从队列中读取或提取条目


例如。

您以一种不同寻常的方式构建了您的解决方案。通常,生产者和消费者本身并不同步,但对他们共享的资源的访问是同步的

考虑这个例子。在这里,
MyQueue
的一个实例是共享资源,它具有同步方法。生产者和消费者本身不同步

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

class MyQueue {
    private int capacity;
    private List<Integer> queue = new LinkedList<>();

    public MyQueue(int capacity) {
        this.capacity = capacity;
    }

    public synchronized void enqueue(int item) throws InterruptedException {
        while (queue.size() == this.capacity) {
            wait();
        }

        System.out.println("Thread " + Thread.currentThread().getName() +
                           " producing " + item);
        queue.add(item);

        if (queue.size() == 1) {
            notifyAll();
        }
    }

    public synchronized int dequeue() throws InterruptedException {
        int item;

        while (queue.size() == 0) {
            wait();
        }

        item = queue.remove(0);

        System.out.println("Thread " + Thread.currentThread().getName() +
                           " consuming " + item);

        if (queue.size() == (capacity - 1)) {
            notifyAll();
        }

        return item;
    }
}

public class ProducerConsumer {
    private static class Producer implements Runnable {
        private MyQueue queue;
        private Random random = new Random();

        public Producer(MyQueue queue) {
            this.queue = queue;
        }

        public void run() {
            try {
                for (;;) {
                    queue.enqueue(random.nextInt());
                    Thread.sleep((int)(Math.random() * 3000) + 1000);
                }
            } catch (InterruptedException ex) {
                System.out.println(Thread.currentThread().getName() +
                        " interrupted");
            }
        }
    }

    private static class Consumer implements Runnable {
        private MyQueue queue;

        public Consumer(MyQueue queue) {
            this.queue = queue;
        }

        public void run() {
            try {
                for (;;) {
                    queue.dequeue();
                    Thread.sleep((int)(Math.random() * 5000) + 3000);
                }
            } catch (InterruptedException ex) {
                System.out.println(Thread.currentThread().getName() +
                        " interrupted");
            }
        }
    }

    public static void main(String[] args) {
        MyQueue queue = new MyQueue(10);

        new Thread(new Producer(queue), "Producer 1").start();
        new Thread(new Producer(queue), "Producer 2").start();
        new Thread(new Consumer(queue), "Consumer 1").start();
        new Thread(new Consumer(queue), "Consumer 2").start();
    }
}

谢谢你的回答。但是我不明白我的代码和文章中的代码有什么不同。谢谢你!我明白了!
$ java ProducerConsumer
Thread Producer 1 producing 1380029295
Thread Consumer 1 consuming 1380029295
Thread Producer 2 producing 1449212482
Thread Consumer 2 consuming 1449212482
Thread Producer 2 producing -1845586946
Thread Producer 1 producing -1072820603
Thread Producer 1 producing 1224861300
Thread Producer 2 producing 507431251
Thread Consumer 2 consuming -1845586946
Thread Consumer 1 consuming -1072820603
Thread Producer 2 producing -1305630628
Thread Producer 1 producing 1413011254
Thread Producer 2 producing -222621018
Thread Consumer 2 consuming 1224861300
Thread Producer 1 producing -1628544536
Thread Consumer 1 consuming 507431251