如何实现多个生产者和多个消费者的生产者消费者问题? 我们应该如何创建线程?
答案 0 :(得分:3)
Sun有一个Concurrency教程,涵盖了基本的线程类。有关Defining and Starting a Thread的信息可以很好地回答您如何创建线程问题。
答案 1 :(得分:2)
也许你应该更多地使用goole: - )
请尝试This article和this source code了解详情。
答案 2 :(得分:1)
创建一个生产者和一个消费者类,它们都是扩展Thread类,实现Runnable接口,并在需要时调用它们。你在哪里被困?
答案 3 :(得分:0)
ConcurrentQueue q = new ConcurrentQueue(100);
ExecutorService service = Executors.newFixedThreadPool(20);
service.execute(new Producer(q));
for (int i=0; i < 18; i++) {
service.execute(new Consumer(q));
}
Consumer
和Producer
都是自定义类,扩展了Runnable并将Queue
作为构造函数参数。
答案 4 :(得分:0)
此类通过一个有限的阻塞队列将任意数量的生产者连接到任意数量的消费者。
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public abstract class ProducerConsumer<E> {
private final BlockingQueue<Optional<E>> queue;
public ProducerConsumer(
int numProducerThreads, int numConsumerThreads, int queueCapacity) {
if (numProducerThreads < 1 || numConsumerThreads < 1 || queueCapacity < 1) {
throw new IllegalArgumentException();
}
queue = new ArrayBlockingQueue<Optional<E>>(queueCapacity);
final ExecutorService executor =
Executors.newFixedThreadPool(numProducerThreads + numConsumerThreads);
try {
// Start producer threads
final List<Future<?>> producerFutures = new ArrayList<>();
final AtomicInteger numLiveProducers = new AtomicInteger();
for (int i = 0; i < numProducerThreads; i++) {
producerFutures.add(executor.submit(() -> {
numLiveProducers.incrementAndGet();
// Run producer
producer();
// When last producer finishes, deliver poison pills to consumers
if (numLiveProducers.decrementAndGet() == 0) {
for (int j = 0; j < numConsumerThreads; j++) {
queue.put(Optional.empty());
}
}
return null;
}));
}
// Start consumer threads
final List<Future<?>> consumerFutures = new ArrayList<>();
for (int i = 0; i < numConsumerThreads; i++) {
consumerFutures.add(executor.submit(() -> {
// Run Consumer
consumer();
return null;
}));
}
// Wait for all producers to complete
completionBarrier(producerFutures, false);
// Shut down any consumers that are still running after producers complete
completionBarrier(consumerFutures, false);
} finally {
executor.shutdownNow();
}
}
private static void completionBarrier(List<Future<?>> futures, boolean cancel) {
for (Future<?> future : futures) {
try {
if (cancel) {
future.cancel(true);
}
future.get();
} catch (CancellationException | InterruptedException e) {
// Ignore
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
}
protected void produce(E val) {
try {
queue.put(Optional.of(val));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
protected Optional<E> consume() {
try {
return queue.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/** Producer loop. Call {@link #produce(E)} for each element. */
public abstract void producer();
/**
* Consumer thread. Call {@link #consume()} to get each successive element,
* until an empty {@link Optional} is returned.
*/
public abstract void consumer();
}
用法如下:
new ProducerConsumer<Integer>(/* numProducerThreads = */ 1, /* numConsumerThreads = */ 4,
/* queueCapacity = */ 10) {
@Override
public void producer() {
for (int i = 0; i < 100; i++) {
System.out.println("Producing " + i);
produce(i);
}
}
@Override
public void consumer() {
for (Optional<Integer> opt; (opt = consume()).isPresent; ) {
int i = opt.get();
System.out.println("Got " + i);
}
}
};