我如何针对生产者消费者问题优化以下代码
how can i optimise following code for producer consumer problem
我有 1 个生产者和 2 个(多个)消费者。
以下代码工作正常(没有竞争条件 IMO)但问题是每当缓冲区为空时,每个消费者都在执行无限循环,这只是等待资源。
我该如何优化它?我正在考虑使用类似通知消费者的方法,以防任何东西被添加到缓冲区但在实施中遇到问题。
public class Test {
public static void main(String[] args) {
Assembly assembly = new Assembly(new ArrayList<>(), new ReentrantLock(true));
new Thread(new Runnable() {
@Override
public void run() {
assembly.consume();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
assembly.produce();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
assembly.consume();
}
}).start();
}
}
class Assembly {
List<Integer> buffer;
Lock bufferLock;
public Assembly(List<Integer> buffer, Lock bufferLock) {
this.buffer = buffer;
this.bufferLock = bufferLock;
}
public void produce() {
Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 99};
Random random = new Random();
for (Integer num : nums) {
try {
bufferLock.lock();
buffer.add(num);
if (num != 99) {
System.out.println("Added: " + num);
}
} finally {
bufferLock.unlock();
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
}
public void consume() {
while (true) {
try {
bufferLock.lock();
if (buffer.isEmpty()) {
**IS SOME OPTIMISATION POSSIBLE HERE?**
continue;
}
if (buffer.get(0).equals(99)) {
break;
}
System.out.println(
"Removed: " + buffer.remove(0) + " by " + Thread.currentThread().getName());
} finally {
bufferLock.unlock();
}
}
}
}
使用 semaphore 而不是尝试自己动手。消费者将等到 'item' 可用,并且只有一个人会醒来拿到商品。
经典的 producer-consumer solution 使用两个信号量,'other' 一个被生产者用来等待 'free slot' 可用。否则,生产者可能会超越消费者跟上的能力。你的程序看起来对生产有一个小的有限限制,所以这可能不适用于这里。
使用 Semaphore
到 add/remove 个可用元素
public class ProducerConsumer {
List<Integer> buffer = new ArrayList<>();
Semaphore available = new Semaphore(0);
public static void main(String... args) {
ProducerConsumer pc = new ProducerConsumer();
new Thread(pc::consume).start();
new Thread(pc::produce).start();
new Thread(pc::consume).start();
}
public void produce() {
Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 99};
Random random = new Random();
for (Integer num : nums) {
try {
synchronized (buffer) {
buffer.add(num);
}
available.release();
System.out.println("Added: " + num);
} finally {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
}
public void consume() {
while (true) {
try {
available.acquire();
synchronized (buffer) {
if (buffer.get(0).equals(99)) {
break;
}
System.out.println(
"Removed: " + buffer.remove(0) + " by " + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
您的(消费者)线程将被阻塞,直到有新项目可用。
有输出
Added: 1
Removed: 1 by Thread-0
Added: 2
Removed: 2 by Thread-2
Added: 3
Removed: 3 by Thread-0
...
我有 1 个生产者和 2 个(多个)消费者。
以下代码工作正常(没有竞争条件 IMO)但问题是每当缓冲区为空时,每个消费者都在执行无限循环,这只是等待资源。
我该如何优化它?我正在考虑使用类似通知消费者的方法,以防任何东西被添加到缓冲区但在实施中遇到问题。
public class Test {
public static void main(String[] args) {
Assembly assembly = new Assembly(new ArrayList<>(), new ReentrantLock(true));
new Thread(new Runnable() {
@Override
public void run() {
assembly.consume();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
assembly.produce();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
assembly.consume();
}
}).start();
}
}
class Assembly {
List<Integer> buffer;
Lock bufferLock;
public Assembly(List<Integer> buffer, Lock bufferLock) {
this.buffer = buffer;
this.bufferLock = bufferLock;
}
public void produce() {
Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 99};
Random random = new Random();
for (Integer num : nums) {
try {
bufferLock.lock();
buffer.add(num);
if (num != 99) {
System.out.println("Added: " + num);
}
} finally {
bufferLock.unlock();
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
}
public void consume() {
while (true) {
try {
bufferLock.lock();
if (buffer.isEmpty()) {
**IS SOME OPTIMISATION POSSIBLE HERE?**
continue;
}
if (buffer.get(0).equals(99)) {
break;
}
System.out.println(
"Removed: " + buffer.remove(0) + " by " + Thread.currentThread().getName());
} finally {
bufferLock.unlock();
}
}
}
}
使用 semaphore 而不是尝试自己动手。消费者将等到 'item' 可用,并且只有一个人会醒来拿到商品。
经典的 producer-consumer solution 使用两个信号量,'other' 一个被生产者用来等待 'free slot' 可用。否则,生产者可能会超越消费者跟上的能力。你的程序看起来对生产有一个小的有限限制,所以这可能不适用于这里。
使用 Semaphore
到 add/remove 个可用元素
public class ProducerConsumer {
List<Integer> buffer = new ArrayList<>();
Semaphore available = new Semaphore(0);
public static void main(String... args) {
ProducerConsumer pc = new ProducerConsumer();
new Thread(pc::consume).start();
new Thread(pc::produce).start();
new Thread(pc::consume).start();
}
public void produce() {
Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 99};
Random random = new Random();
for (Integer num : nums) {
try {
synchronized (buffer) {
buffer.add(num);
}
available.release();
System.out.println("Added: " + num);
} finally {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
}
}
}
}
public void consume() {
while (true) {
try {
available.acquire();
synchronized (buffer) {
if (buffer.get(0).equals(99)) {
break;
}
System.out.println(
"Removed: " + buffer.remove(0) + " by " + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
您的(消费者)线程将被阻塞,直到有新项目可用。
有输出
Added: 1
Removed: 1 by Thread-0
Added: 2
Removed: 2 by Thread-2
Added: 3
Removed: 3 by Thread-0
...