2017-10-05 8 views
0

私は次のコードを実行すると:bare ThreadPoolExecutorを使用してMoreExecutors.newDirectExecutorService()の動作を取得するにはどうすればよいですか?

package foo.trials; 

import com.google.common.util.concurrent.MoreExecutors; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.util.Random; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Future; 
import java.util.concurrent.Semaphore; 
import java.util.concurrent.SynchronousQueue; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 

public class DirectExecutorService { 
    private static final Logger logger_ = LoggerFactory.getLogger(DirectExecutoService.class); 

    public static void main(String[] args) { 
     boolean useGuava = true; 

     final ExecutorService directExecutorService; 
     if (useGuava) { 
      directExecutorService = MoreExecutors.newDirectExecutorService(); 
     } else { 
      directExecutorService = new ThreadPoolExecutor(
        0, 1, 0, TimeUnit.DAYS, 
        new SynchronousQueue<Runnable>(), 
        new ThreadPoolExecutor.CallerRunsPolicy()); 
      directExecutorService.submit(new BlockingCallable()); 
     } 

     Future<Boolean> future = directExecutorService.submit(new MyCallable()); 
     try { 
      logger_.info("Result: {}", future.get()); 
     } catch (InterruptedException e) { 
      logger_.error("Unexpected: Interrupted!", e); 
     } catch (ExecutionException e) { 
      logger_.error("Unexpected: Execution exception!", e); 
     } 
     logger_.info("Exiting..."); 
    } 

    static class MyCallable implements Callable<Boolean> { 
     static final Random _random = new Random(); 
     @Override 
     public Boolean call() throws Exception { 
      logger_.info("In call()"); 
      return _random.nextBoolean(); 
     } 
    } 

    static class BlockingCallable implements Callable<Boolean> { 

     Semaphore semaphore = new Semaphore(0); 
     @Override 
     public Boolean call() throws Exception { 
      semaphore.acquire(); // this will never succeed. 
      return true; 
     } 
    } 
} 

を、私は、実行のすべてがmainのスレッドで起こる次の出力

13:36:55.960 [main] INFO a.t.DirectExecutoService - In call() 
13:36:55.962 [main] INFO a.t.DirectExecutoService - Result: true 
13:36:55.963 [main] INFO a.t.DirectExecutoService - Exiting... 

注意を取得します。特に、呼び出し可能な呼び出しのgetは、呼び出し元のスレッドにディスパッチされます。もちろん、これはMoreExecutors.newDirectExecutorService()から驚くことはありません。

変数useGuavafalseに設定すると、同様の結果が得られます。

13:45:14.264 [main] INFO a.t.DirectExecutoService - In call() 
13:45:14.267 [main] INFO a.t.DirectExecutoService - Result: true 
13:45:14.268 [main] INFO a.t.DirectExecutoService - Exiting... 

しかし、私は次の行に

directExecutorService.submit(new BlockingCallable()); 

をコメントアウトした場合、私は次の出力を取得します。

13:37:27.355 [pool-1-thread-1] INFO a.t.DirectExecutoService - In call() 
13:37:27.357 [main] INFO a.t.DirectExecutoService - Result: false 
13:37:27.358 [main] INFO a.t.DirectExecutoService - Exiting... 

1は、呼び出し可能なの呼び出しが別のスレッドpool-1-thread-1で行わ見ることができるように。なぜこのようなことが起こるのか説明できると思います。おそらくスレッドプールは利用可能なスレッドを最大1つ持つことができるので、第1呼び出しはBlockingCallableで消費された余分なスレッドにディスパッチされます。

ExecutorService私はどのようにしてDirectExecutorServiceを実行するのですか?人工的に終了しない呼び出し可能なスレッドを人工的に焼く必要はありませんか?

なぜ私はこれを求めていますか?

  1. 私はguavaをバージョン11.0で使用するコードベースを使用しています。私はそれを17.0+にアップグレードすることを避ける必要があります - できるならばMoreExecutors.newDirectExecutorService() - を提供します。
  2. ThreadPoolExecutorは、maxThreadsを0に設定することはできません。それが許可されていればそれは奇妙ですが、そうしてしまえば、私の問題も解決しました。
  3. 最後には、私はこの動作に気づくことに驚いた - 私は(誤って)CallerRunsPolicyを使用すると、すべてのcallCallableすべてのsが呼び出し側のスレッドで実行させるだろうと想定していました。だから、私は自分の経験を入れてそこにハックして、誰かがこれを理解しようと燃え尽きた時間を節約できるようにしたかったのです。 :(

は1つが17.0+?

答えて

2

グアバにアップグレードすることができない場合の動作のようなDirectExecutorServiceを達成するが、より良い/より多くの慣用的な方法である場合の動作のようなDirectExecutorServiceを達成するために、より良い/より多くの慣用的な方法はありますグアバ17.0+にアップグレードできません。

ここで問題が発生した場合は、MoreExecutors.sameThreadExecutor()を使用してください。それは新しいメソッドに移動しました(とdirectExecutor()が追加されました)の前に、それは基本的にnewDirectExecutorService()だ、Javadocを参照してください。

導入されたバージョン:18.0(10.0以降MoreExecutors.sameThreadExecutor()として存在)

ところで

:あなたは本当にアップグレードする必要があります最新のグアバに、あなたはほぼ6歳の1つを使用しています!

+0

これは、ありがとうございます!アップグレードについてのポイントがよく取られます。 –

関連する問題