我是使用Java线程池的新手。现在我有一个用于单元测试的用例,当一个新任务到来并且当前线程号是最大数并且队列已满。我知道在这种情况下RejectedExecutionException
会被抛出。但是如何最好地制作这个场景,我现在能想到的是这样的事情:
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(1);
ExecutorService ex = new ThreadPoolExecutor(2, 2, 60L, TimeUnit.MILLISECONDS, queue);
int rejected = 0;
try{
while (true){
ex.submit(() -> {
System.out.println("Queue remaining size: " + queue.remainingCapacity());
System.out.println("Thread amount in pool: " + ((ThreadPoolExecutor)ex).getPoolSize() + "\n");
});
}
}
catch (RejectedExecutionException e){
System.out.println(++rejected);
}
这是基本的想法,我需要使用EasyMock转换它,如果它是正确的方法。我想知道是否有更好的方法,如果使用EasyMock而不是继续提交任务,直到线程和队列已满。
答案 0 :(得分:1)
我特别不熟悉EasyMock,但一般的方法应该是模拟ThreadPoolExecutor。
答案 1 :(得分:1)
这是基本的想法,我需要使用EasyMock转换它,如果它是正确的方法。我想知道是否有更好的方法,如果使用EasyMock而不是继续提交任务,直到线程和队列已满。
EasyMock所做的任何事情都可能比匿名Runnable
更多地使用代码。你当然可以这样做,但你会使用IAnswer
对象而不是Runnable
,所以我不确定它会好得多。
真正的问题是你在测试什么?您是否真的确保ThreadPoolExecutor
正在做这项工作,或者您是否真的试图嘲笑ExecutorService
或@Warren提到ThreadPoolExecutor
。
我在Thread.sleep(1000)
中执行Runnable
并提交其中的4个而不是while
循环。您还可以在开始时创建一个对象并多次提交。请原谅Java 7代码:
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(1);
ExecutorService ex = new ThreadPoolExecutor(2, 2, 60L, TimeUnit.MILLISECONDS, queue);
Runnable runnable = new Runnable() {
@Override
public void run() {
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
}
};
try {
ex.submit(runnable); // 1st thread
ex.submit(runnable); // 2nd thread
ex.submit(runnable); // 1st queued
ex.submit(runnable); // rejected
} catch (RejectedExecutionException e) {
System.out.println("rejected");
}
答案 2 :(得分:0)
您可以将执行代码移动到一个新类,您可以在其中轻松模拟依赖项:
class MyExecuter extends Executer{
private final ExecuterService executerService;
private final PrintStream out;
MyExecuter(ExecutorService executerService, PrintStream out){
this.executerService = executerService;
this.out = out;
}
@override
public void execute(Runnable r) {
int rejected = 0;
try{
while (true)
{
executerService.submit(() -> {
// do your business logic which usually does not care about the executor or the queue...
});
}
}
catch (RejectedExecutionException e)
{
out.println(++rejected);
}
}
}
您的代码将更改为:
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(1);
ExecutorService ex = new ThreadPoolExecutor(2, 2, 60L, TimeUnit.MILLISECONDS, queue);
Executor mex = new MyExcecutor(ex, System.out);
mex.execute();
现在,您可以为MyExcecutor
创建一个测试,以获取ExecutorService
和PrintStream
的模拟,以便您可以验证与它们的互动。
答案 3 :(得分:0)
一个简单的解决方案:
在提交任务之前致电shutdown。
如果您在submit()
之后致电shutdown(
,您将获得此类型的执行:
java.util.concurrent.RejectedExecutionException: Task MyRunnable@3dcc0a0f
rejected from java.util.concurrent.ThreadPoolExecutor