[英]communication between threads in the different pools java
我有兩個本地線程池,一個池有4個線程,第二個池有5個線程。
我希望這兩個池彼此通信。
例如,第一個池的第二個線程(1.2)與第二個池的第五個線程(2.5)通信,即
1.2 -> 2.5
1.1 -> 2.2
1.3 -> 2.1
1.4 -> 2.3
1.2已完成將消息發送到2.5,並希望將另一條消息發送到第二個池,但是2.5仍然很忙,但是2.4忙於處理1.2中的消息
如何使第一個池中的線程與第二個池中的第一個空閑線程通信?
如何在Java中實現它?
也許我應該使用消息代理或類似的東西? (或BlockingQueue,Exchanger / Pipereader )
謝謝
(您的示例尚不清楚,但我認為您正在要求一種方案,其中一個池中的線程不關心另一個池中的哪個線程獲取消息。)
可能有很多方法可以做到這一點,但是一個簡單的方法是:
消息代理也可以工作,但可能會過大。 您很可能不想要成熟的消息代理的可靠性/持久性/分發。
如何使第一個池中的線程與第二個池中的第一個空閑線程通信?
我不確定您是否還有其他特定需求,但是如果兩個池都是本地的,並且您只是願意實現典型的生產者-消費者模式,其中N線程(作為池的一部分)充當生產者,另一個M線程(作為另一個池的一部分)充當使用者,並且您不在乎第二個池的哪個線程實例處理一條消息,我將采用BlockingQueue
實現。
您采用BlockingQueue
一個實例(例如ArrayBlockingQueue
或LinkedBlockingQueue
或PriorityBlockingQueue
並且包java.util.concurrent
中包含更多實現),並在實際的池線程之間共享該實例,同時限制take()
只能由使用者線程和通過任何使用者線程。
如何在Java中實現它?
您可以如下創建池,
ExecutorService pool_1 = Executors.newFixedThreadPool(4);
ExecutorService pool_2 = Executors.newFixedThreadPool(4);
然后,將實際線程分配給共享阻塞隊列的這些池。 可以像下面這樣創建線程-它只是一個偽代碼。
public class Pool1Runnable implements Runnable {
private final BlockingQueue queue;
public Pool1Runnable(BlockingQueue queue){
this.queue=queue;
}
@Override
public void run() {
System.out.println("Pool1Runnable");
}
}
現在,您為pool2編寫線程實現,並確保其run()
實現在隊列上使用take()
。
創建池實例和線程實例-為生產者和使用者分離(為所有線程提供一個隊列實例,使其充當通信通道),然后對池執行這些線程實例。
希望能幫助到你 !!
其他人指出的最直接的方法是在池之間具有BlockingQueue 。 如果我沒記錯的話,您的問題就和讓多個生產者和多個消費者分別發送和處理消息一樣。
這是可以建立的一種實現。 幾乎沒有添加注釋的參數,您可以根據自己的問題場景進行調整。 基本上,您有2個池和另一個池來並行調用生產者和使用者。
public class MultiProducerConsumer {
private static final int MAX_PRODUCERS = 4;
private static final int MAX_CONSUMERS = 5;
private ExecutorService producerPool = new ThreadPoolExecutor(2, MAX_PRODUCERS, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
private ExecutorService consumerPool = new ThreadPoolExecutor(2, MAX_CONSUMERS, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
//ThreadPool for holding the main threads for consumer and producer
private ExecutorService mainPool = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
/**
* Indicates the stopping condition for the consumer, without this it has no idea when to stop
*/
private AtomicBoolean readerComplete = new AtomicBoolean(false);
/**
* This is the queue for passing message from producer to consumer.
* Keep queue size depending on how slow is your consumer relative to producer, or base it on resource constraints
*/
private BlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
MultiProducerConsumer multiProducerConsumer = new MultiProducerConsumer();
multiProducerConsumer.process();
System.out.println("Time taken in seconds - " + (System.currentTimeMillis() - startTime)/1000f);
}
private void process() throws InterruptedException {
mainPool.execute(this::consume);
mainPool.execute(this::produce);
Thread.sleep(10); // allow the pool to get initiated
mainPool.shutdown();
mainPool.awaitTermination(5, TimeUnit.SECONDS);
}
private void consume() {
try {
while (!readerComplete.get()) { //wait for reader to complete
consumeAndExecute();
}
while (!queue.isEmpty()) { //process any residue tasks
consumeAndExecute();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
consumerPool.shutdown();
consumerPool.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void consumeAndExecute() throws InterruptedException {
if (!queue.isEmpty()) {
String msg = queue.take(); //takes or waits if queue is empty
consumerPool.execute(() -> {
System.out.println("c-" + Thread.currentThread().getName() + "-" + msg);
});
}
}
private void produce() {
try {
for (int i = 0; i < MAX_PRODUCERS; i++) {
producerPool.execute(() -> {
try {
String random = getRandomNumber() + "";
queue.put(random);
System.out.println("p-" + Thread.currentThread().getName() + "-" + random);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
} finally {
try {
Thread.sleep(10); //allow pool to get initiated
producerPool.shutdown();
producerPool.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
readerComplete.set(true); //mark producer as done, so that consumer can exit
}
}
private int getRandomNumber() {
return (int) (Math.random() * 50 + 1);
}
}
這是輸出:
p-pool-1-thread-2-43
p-pool-1-thread-2-32
p-pool-1-thread-2-12
c-pool-2-thread-1-43
c-pool-2-thread-1-12
c-pool-2-thread-2-32
p-pool-1-thread-1-3
c-pool-2-thread-1-3
Time taken in seconds - 0.1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.