Java线程池抛出RejectedExecutionException的单元测试
我不熟悉使用Java线程池。现在我有了一个单元测试用例,当一个新任务到来,当前线程数为max number,队列已满时。我知道在这种情况下,将抛出Java线程池抛出RejectedExecutionException的单元测试,java,multithreading,unit-testing,Java,Multithreading,Unit Testing,我不熟悉使用Java线程池。现在我有了一个单元测试用例,当一个新任务到来,当前线程数为max number,队列已满时。我知道在这种情况下,将抛出RejectedExecutionException。但如何最好地创造这种情景,我现在能想到的是: LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(1); ExecutorService ex = new ThreadPoolExec
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);
}
LinkedBlockingQueue队列=新的LinkedBlockingQueue(1);
ExecutorService ex=新的ThreadPoolExecutor(2,2,60L,TimeUnit.ms,队列);
int=0;
试一试{
while(true){
例如提交(()->{
System.out.println(“队列剩余大小:+Queue.remainingCapacity());
System.out.println(“池中的线程数量:”+((ThreadPoolExecutor)ex).getPoolSize()+“\n”);
});
}
}
捕获(拒绝执行异常e){
System.out.println(++拒绝);
}
这是基本的想法,我需要使用EasyMock转换它,如果它是正确的方式。我想知道如果使用EasyMock而不是一直提交任务直到线程和队列都满了,是否有更好的方法 我对EasyMock不太熟悉,但一般的方法应该是模拟ThreadPoolExecutor。您可以将执行代码移动到一个新类,在这个类中可以轻松模拟依赖项:
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();
LinkedBlockingQueue队列=新的LinkedBlockingQueue(1);
ExecutorService ex=新的ThreadPoolExecutor(2,2,60L,TimeUnit.ms,队列);
执行器mex=新的MyExcecutor(例如,System.out);
execute();
现在,您可以为myexecutor
创建一个测试,获取ExecutorService
和PrintStream
的模拟,以便验证与它们的交互。一个简单的解决方案:
在提交任务之前先调用
如果在关闭(
)后调用submit()
,您将获得以下类型的执行选项:
java.util.concurrent.RejectedExecutionException: Task MyRunnable@3dcc0a0f
rejected from java.util.concurrent.ThreadPoolExecutor
这是基本的想法,我需要使用EasyMock转换它,如果它是正确的方式。我想知道如果使用EasyMock而不是一直提交任务直到线程和队列都满了,是否有更好的方法
EasyMock所做的任何事情都很可能需要比您的匿名Runnable
更多的代码。您当然可以这样做,但您会使用IAnswer
对象而不是Runnable
,因此我不确定它是否更好
真正的问题是你在测试什么?您是否真的要确保ThreadPoolExecutor
正在完成它的工作,或者您真的要模拟ExecutorService
或者@Warren提到的ThreadPoolExecutor
我会在你的Runnable
中执行一个线程。sleep(1000)
,然后提交其中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");
}
BlockingQueue=newlinkedblockingqueue(1);
ExecutorService ex=新的ThreadPoolExecutor(2,2,60L,TimeUnit.ms,队列);
Runnable Runnable=新的Runnable(){
@凌驾
公开募捐{
尝试{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}
}
};
试一试{
ex.submit(runnable);//第一个线程
ex.submit(可运行);//第二个线程
ex.submit(runnable);//第一个排队
例如提交(可运行);//被拒绝
}捕获(拒绝执行异常e){
系统输出打印项次(“拒绝”);
}
我支持这一点,这样做的方法是删除ThreadPoolExecutor
的实例化和LinkedBlockingQueue
它依赖于类外并将其注入(最好作为构造函数参数)。然后很容易用模拟替换ThreadPoolExecutor
。由于ThreadPoolExecutor
正在实现接口Executor
,因此构造函数参数应为该接口类型。