这是一篇快速而肮脏的文章,但我已承诺将发表我在Playtomic研究的所有内容。
我们正在讨论如何限制ExecutorService可以排队多少个任务。 我们试图 控制服务可以处理多少内存以避免内存不足异常。 该服务接受来自Kafka主题的消息 并通过API。 这些操作以相同的内部逻辑结束,该逻辑是线程化的。
有一种队列BlockingQueue,可以等待直到队列中的某个位置空闲为止。 似乎使用ExecutionService 提交任务时,使用BlockingQueue的对象将等待,直到该队列未满为止。 但不是,ExecutionService拒绝任务。
您知道,反复试验可以节省您阅读手册的时间。 我很自豪地说,这是我第一次阅读本手册。
此测试显示发生了什么:
public class BlockingQueueExecutorServiceTest {
@Test
public void submitTest() {
// Worst case scenario: accept only 1 thread in the queue.
int nThreads = 1;
ExecutorService exService = new ThreadPoolExecutor(
nThreads,
nThreads,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(nThreads));
// Full this with tasks
for (int i = 0; i < 10000; ++i) {
WaitingTask t = new WaitingTask(i);
exService.submit(t);
}
}
private static class WaitingTask implements Runnable {
int index;
public WaitingTask(int index) {
this.index = index;
}
@Override
public void run() {
try {
log.info("Running task {}", index);
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@550dbc7a[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@4dbb42b7[Wrapped task = com.playtomic.anemone.matchmaker.service.BlockingQueueExecutorServiceTest$WaitingTask@66f57048]] rejected from java.util.concurrent.ThreadPoolExecutor@21282ed8[Running, pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 0]
at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825)
at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355)
at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
at com.playtomic.anemone.matchmaker.service.BlockingQueueExecutorServiceTest.submitTest(BlockingQueueExecutorServiceTest.java:28)
... more boring stacktrace
如果要等到队列未满,则必须提供一个RejectedExecutionHandler来执行此操作。 例如,Spring的CallerBlocksPolicy。
public class BlockingQueueExecutorServiceTest {
@Test
public void submitTest() {
// Worst case scenario: accept only 1 thread in the queue.
int nThreads = 1;
CallerBlocksPolicy policy = new CallerBlocksPolicy(10000); // 10secs
ExecutorService exService = new ThreadPoolExecutor(
nThreads,
nThreads,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(nThreads),
policy);
// Full this with tasks
for (int i = 0; i < 10000; ++i) {
WaitingTask t = new WaitingTask(i);
exService.submit(t);
}
}
private static class WaitingTask implements Runnable {
int index;
public WaitingTask(int index) {
this.index = index;
}
@Override
public void run() {
try {
log.info("Running task {}", index);
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
这次我们得到:
12:21:32.409 [pool-1-thread-1] INFO com.playtomic.anemone.matchmaker.service.BlockingQueueExecutorServiceTest - Running task 0
12:21:32.422 [main] DEBUG org.springframework.integration.util.CallerBlocksPolicy - Attempting to queue task execution for 10000 milliseconds
12:21:33.420 [pool-1-thread-1] INFO com.playtomic.anemone.matchmaker.service.BlockingQueueExecutorServiceTest - Running task 1
12:21:33.420 [main] DEBUG org.springframework.integration.util.CallerBlocksPolicy - Task execution queued
12:21:33.421 [main] DEBUG org.springframework.integration.util.CallerBlocksPolicy - Attempting to queue task execution for 10000 milliseconds
12:21:34.423 [pool-1-thread-1] INFO com.playtomic.anemone.matchmaker.service.BlockingQueueExecutorServiceTest - Running task 2
from: https://dev.to//playtomic/linkedblockingqueue-and-executorservice-1pc5