在Java中使用wait()和notify()的生产者-消费者程序
我使用低级同步和wait()和notify()在Java中处理典型的生产者-消费者问题。我知道有更好的实现使用java.util.concurrent包中的结构,但我的问题是围绕低级别实现:在Java中使用wait()和notify()的生产者-消费者程序,java,multithreading,producer-consumer,Java,Multithreading,Producer Consumer,我使用低级同步和wait()和notify()在Java中处理典型的生产者-消费者问题。我知道有更好的实现使用java.util.concurrent包中的结构,但我的问题是围绕低级别实现: private static ArrayList<Integer> list = new ArrayList<Integer>(); static Object obj = new Object(); public static void producer() t
private static ArrayList<Integer> list = new ArrayList<Integer>();
static Object obj = new Object();
public static void producer() throws InterruptedException {
synchronized (obj) {
while (true) {
if (list.size() == 10) {
System.out.println("Queue full.. Waiting to Add");
obj.wait();
} else {
int value = new Random().nextInt(100);
if (value <= 10) {
Thread.sleep(200);
System.out.println("The element added was : " + value);
list.add(value);
obj.notify();
}
}
}
}
}
public static void consumer() throws InterruptedException {
synchronized (obj) {
while (true) {
Thread.sleep(500);
if (list.size() == 0) {
System.out.println("Queue is empty...Waiting to remove");
obj.wait();
} else {
System.out.println("The element removed was : "
+ list.remove(0));
obj.notify();
}
}
}
}
编辑:以下是更正的代码:
private static ArrayList<Integer> list = new ArrayList<Integer>();
private static Object obj = new Object();
public static void producer() throws InterruptedException {
while (true) {
Thread.sleep(500);
if (list.size() == 10) {
System.out.println("Waiting to add");
synchronized (obj) {
obj.wait();
}
}
synchronized (obj) {
int value = new Random().nextInt(10);
list.add(value);
System.out.println("Added to list: " + value);
obj.notify();
}
}
}
public static void consumer() throws InterruptedException {
while (true) {
Thread.sleep(500);
if (list.size() == 0) {
System.out.println("Waiting to remove");
synchronized (obj) {
obj.wait();
}
}
synchronized (obj) {
int removed = list.remove(0);
System.out.println("Removed from list: " + removed);
obj.notify();
}
}
}
private static ArrayList list=new ArrayList();
私有静态对象obj=新对象();
public static void producer()引发InterruptedException{
while(true){
睡眠(500);
if(list.size()==10){
System.out.println(“等待添加”);
同步(obj){
obj.wait();
}
}
同步(obj){
int value=new Random().nextInt(10);
列表。添加(值);
System.out.println(“添加到列表:“+值”);
obj.notify();
}
}
}
public static void consumer()引发InterruptedException{
while(true){
睡眠(500);
if(list.size()==0){
System.out.println(“等待删除”);
同步(obj){
obj.wait();
}
}
同步(obj){
int removed=list.remove(0);
System.out.println(“从列表中删除:”+删除);
obj.notify();
}
}
}
不能使用同一对象在同步块中运行两个线程。当一个方法正在运行时,另一个方法无法运行,直到另一个线程调用wait
method
要解决此问题,您只需将
添加
和删除
放在同步块中即可。有关更多信息,请参阅。生产者和消费者问题是多进程同步问题的经典示例。这描述了共享公共资源的两个进程,生产者和消费者,缓冲区。生产者作业是生成数据并将其放入缓冲区,消费者作业是消费生成的数据并从缓冲区中删除
生产者必须确保在缓冲区已满时不添加任何元素,它应该调用wait()
,直到消费者使用一些数据并通知生产者线程,消费者必须确保它不应该在缓冲区已空时尝试从缓冲区中删除项目,它应该调用wait()
只需等待生产者生成数据并将其添加到缓冲区,然后使用notify
或notifyAll
通知消费者即可
这个问题可以通过使用BlockingQueue
接口来解决,该接口管理生产者和消费者自己的实现
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/*
* To change this license header, choose License Headers in Project `Properties`.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author sakshi
*/
public class ThreadProducer {
static List<Integer> list = new ArrayList<Integer>();
static class Producer implements Runnable {
List<Integer> list;
public Producer(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
synchronized (list) {
for (int i = 0; i < 10; i++) {
if (list.size() >= 1) {
try {
System.out.println("producer is waiting ");
list.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("produce=" + i);
list.add(i);
list.notifyAll();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
//To change body of generated methods, choose Tools | Templates.
}
}
static class Consumer implements Runnable {
List<Integer> list;
public Consumer(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
synchronized (list) {
for (int i = 0; i < 10; i++) {
while (list.isEmpty()) {
System.out.println("Consumer is waiting");
try {
list.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();;
}
}
int k = list.remove(0);
System.out.println("consume=" + k);
list.notifyAll();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
Thread producer = new Thread(new Producer(list));
Thread consumer = new Thread(new Consumer(list));
producer.start();
consumer.start();
}
}
不要使用list.size()==10
,而是可以选中list.size==1
对于生产商而言,一方等待另一方,直到消费者消费。请参阅本课程参考资料{
private final int capacity = 2;
public static int value = 0;
LinkedList < Integer > list;
Resources() {
list = new LinkedList < > ();
}
void consume() throws InterruptedException {
while (true) {
synchronized(this) {
while (list.size() == 0) {
wait();
}
int val = list.removeFirst();
System.out.println("Value consumed:" + val);
notify();
//Thread.sleep(1000);
}
}
}
void produce() throws InterruptedException {
while (true) {
synchronized(this) {
while (list.size() == capacity) {
wait();
}
System.out.println("Value produced:" + value);
list.add(value++);
notify();
Thread.sleep(1000);
}
}
}
}
公共类ProducerConsumerExample{
public static void main(String[] args) {
try {
Resources rs = new Resources();
MyThread5 m1 = new MyThread5(rs, "Producer");
MyThread5 m2 = new MyThread5(rs, "Consumer");
m1.start();
m2.start();
m1.join();
m2.join();
} catch (InterruptedException ex) {
Logger.getLogger(ProducerConsumerExample.class.getName()).log(Level.SEVERE, null, ex);
}
}
}为什么要使用if(list.size()==10)
?@SotiriosDelimanolis只是为了模拟队列的最大大小/深度,您看到它是如何应用的了吗?唯一的问题是,生产者继续一次生成消息,直到消息的最大值(直到列表的大小为10),消费者一次消费全部10条消息。?是的。如果达到列表的最大大小,线程将等待(obj.wait())
。但是在obj.notify()
之后,它应该在中再次继续,而(true)
循环生成notify()
不会释放相应对象的锁。这是一个很好的示例。但最好在Producer中使用while循环on条件,因为存在虚假的唤醒可能性。不幸的是,链接已经死了。
private final int capacity = 2;
public static int value = 0;
LinkedList < Integer > list;
Resources() {
list = new LinkedList < > ();
}
void consume() throws InterruptedException {
while (true) {
synchronized(this) {
while (list.size() == 0) {
wait();
}
int val = list.removeFirst();
System.out.println("Value consumed:" + val);
notify();
//Thread.sleep(1000);
}
}
}
void produce() throws InterruptedException {
while (true) {
synchronized(this) {
while (list.size() == capacity) {
wait();
}
System.out.println("Value produced:" + value);
list.add(value++);
notify();
Thread.sleep(1000);
}
}
}
Resources rs;
String name;
public String getNames() {
return name;
}
public MyThread5(Resources rs, String name) {
this.rs = rs;
this.name = name;
}
@Override
public void run() {
if (this.getNames().equals("Producer")) {
try {
this.rs.produce();
} catch (InterruptedException ex) {
Logger.getLogger(MyThread5.class.getName()).log(Level.SEVERE, null, ex);
}
} else {
try {
this.rs.consume();
} catch (InterruptedException ex) {
Logger.getLogger(MyThread5.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static void main(String[] args) {
try {
Resources rs = new Resources();
MyThread5 m1 = new MyThread5(rs, "Producer");
MyThread5 m2 = new MyThread5(rs, "Consumer");
m1.start();
m2.start();
m1.join();
m2.join();
} catch (InterruptedException ex) {
Logger.getLogger(ProducerConsumerExample.class.getName()).log(Level.SEVERE, null, ex);
}
}