生产者和消费者未按顺序打印答案
Producer & Consumer is not printing answer in order
我正在尝试编写应按以下顺序打印输出的生产者和消费者
consumer 1
produce 1
consumer 2
produce 2
但它没有按顺序给出输出。为了在使用 synchronized 关键字时实现顺序,它甚至不打印任何输出。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.stream.IntStream;
public class ProducerAndCosumer {
ArrayBlockingQueue<Integer> blockingQueue ;
public ProducerAndCosumer(int capacity) {
this.blockingQueue = new ArrayBlockingQueue<Integer>(capacity);
}
public synchronized void consume(int data) {
System.out.println(" consumer " + data);
blockingQueue.offer(data);
}
public synchronized int produce() throws InterruptedException {
int data = blockingQueue.take();
System.out.println(" produce " + data);
return data;
}
public static void main(String[] args) throws InterruptedException {
ProducerAndCosumer pc = new ProducerAndCosumer(10);
Runnable run1 = new Runnable() {
@Override
public void run() {
System.out.println(" Entered consumer runner ");
IntStream.range(1, 20).forEach(pc::consume);
}
};
new Thread(run1).start();
Runnable run2 = new Runnable() {
@Override
public void run() {
System.out.println(" Entered producer runner ");
try {
for (int i = 0 ; i < 30 ; i++) {
pc.produce();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(run2).start();
}
}
请建议我如何解决它。还有一个问题,我们能不能不用等待和通知就实现。
在您的代码中,存在竞争条件问题。您应该提供对 ArrayBlockingQueue
的并发访问。许多可能的变体之一是下一个例子(有两个信号量):
public class ProducerAndConsumer {
private final ArrayBlockingQueue<Integer> blockingQueue ;
private final Semaphore semaphoreOne;
private final Semaphore semaphoreTwo;
public ProducerAndConsumer(int capacity) {
this.blockingQueue = new ArrayBlockingQueue<>(capacity, true);
this.semaphoreOne = new Semaphore(1);
this.semaphoreTwo = new Semaphore(1);
}
public void consume(int data) throws InterruptedException {
semaphoreOne.acquire();
System.out.println(" consumer " + data);
blockingQueue.offer(data);
semaphoreTwo.release();
}
public void produce() throws InterruptedException {
semaphoreTwo.acquire();
int data = blockingQueue.take();
System.out.println(" produce " + data);
semaphoreOne.release();
}
public static void main(String[] args) throws InterruptedException {
ProducerAndConsumer pc = new ProducerAndConsumer(10);
Runnable run1 = () -> {
System.out.println(" Entered consumer runner ");
for (int i = 1; i < 20; i++) {
try {
pc.consume(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable run2 = () -> {
System.out.println(" Entered producer runner ");
try {
for (int i = 0 ; i < 30 ; i++) {
pc.produce();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(run1).start();
new Thread(run2).start();
}
}
这个程序的输出是:
Entered consumer runner
Entered producer runner
consumer 1
produce 1
consumer 2
produce 2
consumer 3
produce 3
consumer 4
produce 4
consumer 5
produce 5
consumer 6
produce 6
consumer 7
produce 7
consumer 8
produce 8
consumer 9
produce 9
consumer 10
produce 10
consumer 11
produce 11
consumer 12
produce 12
consumer 13
produce 13
consumer 14
produce 14
consumer 15
produce 15
consumer 16
produce 16
consumer 17
produce 17
consumer 18
produce 18
consumer 19
produce 19
此外,当您声明两个方法时 consume
produce
synchronized
您将遇到死锁,因为这两个方法将尝试通过一个监视器同步(对象 ProducerAndConsumer
), 请参见 ThreadDump
我正在尝试编写应按以下顺序打印输出的生产者和消费者
consumer 1
produce 1
consumer 2
produce 2
但它没有按顺序给出输出。为了在使用 synchronized 关键字时实现顺序,它甚至不打印任何输出。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.stream.IntStream;
public class ProducerAndCosumer {
ArrayBlockingQueue<Integer> blockingQueue ;
public ProducerAndCosumer(int capacity) {
this.blockingQueue = new ArrayBlockingQueue<Integer>(capacity);
}
public synchronized void consume(int data) {
System.out.println(" consumer " + data);
blockingQueue.offer(data);
}
public synchronized int produce() throws InterruptedException {
int data = blockingQueue.take();
System.out.println(" produce " + data);
return data;
}
public static void main(String[] args) throws InterruptedException {
ProducerAndCosumer pc = new ProducerAndCosumer(10);
Runnable run1 = new Runnable() {
@Override
public void run() {
System.out.println(" Entered consumer runner ");
IntStream.range(1, 20).forEach(pc::consume);
}
};
new Thread(run1).start();
Runnable run2 = new Runnable() {
@Override
public void run() {
System.out.println(" Entered producer runner ");
try {
for (int i = 0 ; i < 30 ; i++) {
pc.produce();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(run2).start();
}
}
请建议我如何解决它。还有一个问题,我们能不能不用等待和通知就实现。
在您的代码中,存在竞争条件问题。您应该提供对 ArrayBlockingQueue
的并发访问。许多可能的变体之一是下一个例子(有两个信号量):
public class ProducerAndConsumer {
private final ArrayBlockingQueue<Integer> blockingQueue ;
private final Semaphore semaphoreOne;
private final Semaphore semaphoreTwo;
public ProducerAndConsumer(int capacity) {
this.blockingQueue = new ArrayBlockingQueue<>(capacity, true);
this.semaphoreOne = new Semaphore(1);
this.semaphoreTwo = new Semaphore(1);
}
public void consume(int data) throws InterruptedException {
semaphoreOne.acquire();
System.out.println(" consumer " + data);
blockingQueue.offer(data);
semaphoreTwo.release();
}
public void produce() throws InterruptedException {
semaphoreTwo.acquire();
int data = blockingQueue.take();
System.out.println(" produce " + data);
semaphoreOne.release();
}
public static void main(String[] args) throws InterruptedException {
ProducerAndConsumer pc = new ProducerAndConsumer(10);
Runnable run1 = () -> {
System.out.println(" Entered consumer runner ");
for (int i = 1; i < 20; i++) {
try {
pc.consume(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable run2 = () -> {
System.out.println(" Entered producer runner ");
try {
for (int i = 0 ; i < 30 ; i++) {
pc.produce();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
new Thread(run1).start();
new Thread(run2).start();
}
}
这个程序的输出是:
Entered consumer runner
Entered producer runner
consumer 1
produce 1
consumer 2
produce 2
consumer 3
produce 3
consumer 4
produce 4
consumer 5
produce 5
consumer 6
produce 6
consumer 7
produce 7
consumer 8
produce 8
consumer 9
produce 9
consumer 10
produce 10
consumer 11
produce 11
consumer 12
produce 12
consumer 13
produce 13
consumer 14
produce 14
consumer 15
produce 15
consumer 16
produce 16
consumer 17
produce 17
consumer 18
produce 18
consumer 19
produce 19
此外,当您声明两个方法时 consume
produce
synchronized
您将遇到死锁,因为这两个方法将尝试通过一个监视器同步(对象 ProducerAndConsumer
), 请参见 ThreadDump