2017-01-02 1 views
1

Javaスレッドプールを初めて使用しています。今私は新しいタスクが来て、現在のスレッド番号が最大数であり、キューがいっぱいであるときにユニットテストのユースケースを持っています。私はこの場合、RejectedExecutionExceptionが投げられることを知っています。しかし、どのように最高のこのシナリオを生成するために、私は今考えることができますが、このようなものです: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を使用する方が良い方法があるのだろうかと思います。

答えて

1

これが基本的な考えであり、私はそれが正しい方法である場合は、この使用してEasyMockを変換する必要があります。スレッドとキューがいっぱいになるまで、タスクを送信し続けるのではなく、EasyMockを使用する方が良い方法があるのだろうかと思います。

EasyMockが行うすべてのことは、匿名のコードよりも多くのコードを取得する可能性がありますRunnable。あなたは確かにそれを行うことができますが、Runnableの代わりにIAnswerオブジェクトを使用するので、はるかに良いとは思いません。

実際の質問は何をテストしているのですか? ThreadPoolExecutorが仕事をしているか、実際にExecutorServiceを模倣しようとしているのか、@WarrenはThreadPoolExecutorと言っているのですか?

RunnableThread.sleep(1000)を入れて、whileループの代わりに4個を送信します。最初に1つのオブジェクトを作成し、複数回送信することもできます。私はこれをサポート

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"); 
} 
+0

ありがとう、これは私が必要なものです – michael

1

私は特にEasyMockに精通していませんが、一般的なアプローチはThreadPoolExecutorをモックアウトすることです。

+1

及びそうする方法は、 'ThreadPoolExecutor'と' LinkedBlockingQueue'それはクラスの外に依存するのインスタンス化を削除し、(好ましくはコンストラクタとしてそれを注入することである:Javaの7のコードを言い訳してください引数)。それで、 'ThreadPoolExecutor'をモックで置き換えるのは簡単です。 'ThreadPoolExecutor'がインタフェース' Executor'を実装しているので、コンストラクタパラメータはそのインタフェース型でなければなりません。 –

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 = mew MyExcecutor(ex, System.out); 
mex.execute(); 

今あなたがテストを作成することができますMyExcecutorの場合はExecutorServicePrintStreamのモックを取得して、それらとのやり取りを確認できます。

0

一つの簡単な解決策:タスクを提出する前に

コールshutdown

あなたはshutdown(submit()を呼び出した場合)、あなたはexecptionのこのタイプを取得します:

java.util.concurrent.RejectedExecutionException: Task [email protected] 
rejected from java.util.concurrent.ThreadPoolExecutor 
関連する問題