Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程池抛出RejectedExecutionException的单元测试_Java_Multithreading_Unit Testing - Fatal编程技术网

Java线程池抛出RejectedExecutionException的单元测试

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

我不熟悉使用Java线程池。现在我有了一个单元测试用例,当一个新任务到来,当前线程数为max number,队列已满时。我知道在这种情况下,将抛出
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
,因此构造函数参数应为该接口类型。