0

ThreadPoolExecutorのキューの動作を理解しようとしています。以下のプログラムでは、LinkedBlockingQueueを使用すると、一度に1つのタスクしかスレッドプールに送信できません。しかし、LinkedBlockingQueueSynchronousQueueに置き換えた場合、5つのタスクすべてをプールに瞬時に提出できます。この場合、SynchronousQueueLinkedBlockingQueueの違いは?ThreadPoolExecutorのSynchronousQueue

Javaプログラム:

import java.util.concurrent.Executors; 
import java.util.concurrent.LinkedBlockingQueue; 
import java.util.concurrent.SynchronousQueue; 
import java.util.concurrent.ThreadFactory; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 

public class Sample { 
    public static void main(String[] args) throws InterruptedException { 
     LinkedBlockingQueue<Runnable> threadPoolQueue = new LinkedBlockingQueue<>(); 
//  SynchronousQueue<Runnable> threadPoolQueue = new SynchronousQueue<>(); 
     ThreadFactory threadFactory = Executors.defaultThreadFactory(); 
     ThreadPoolExecutor tpe = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, threadPoolQueue, threadFactory); 
     Runnable np; 

     for (int i = 1; i <= 5; i++) { 
      np = new SampleWorker("ThreadPoolWorker " + i); 
      tpe.submit(np); 
     } 

     System.out.println(tpe.getCorePoolSize()); 
     System.out.println(tpe.getPoolSize()); 
     System.out.println(tpe.getActiveCount()); 

     tpe.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 
     tpe.shutdown(); 
     System.out.println("Main task finished"); 
    } 
} 

class SampleWorker implements Runnable { 
    private String workerName; 

    SampleWorker(String tName) { 
     workerName = tName; 
    } 

    @Override 
    public void run() { 
     try { 
      for (int i = 1; i <= 10; i++) { 
       Thread.sleep(3000); 
       System.out.println(this.workerName); 
      } 
      System.out.println(this.workerName + " finished"); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 
+1

は 'SynchronousQueue'と' LinkedBlockingQueue'(の違いを説明して、[この](https://stackoverflow.com/questions/8591610/when-should-i-use-synchronousqueue) – avix

+0

@avixを見てください1のサイズ)。しかしここでは、いずれのキューのサイズも指定していません。また、 'LinkedBlockingQueue'では一度に1つのタスクしか提出できませんでしたが、' SynchronousQueue'では5つのタスクすべてを同時に提出することができました。どちらの場合も 'corePoolSize'を0に設定しました。 'corePoolSize'は' SynchronousQueue'に影響しませんか? – UnahD

+0

@UnahD 'corePoolSize'は基本的な' BlockingQueue'に影響を与えません.'BlockingQueue'ではなく 'ThreadPoolExecutor'のスレッドプールサイズを制御します。また、ドキュメントで言うように、 'SynchronousQueue' [内部容量も1つでもありません](https://docs.oracle.com/javase/9​​/docs/api/java/util/concurrent/SynchronousQueue .html)および 'size()'(常にゼロを返します)(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/SynchronousQueue.html#size()) –

答えて

1

あなたはThreadPoolExecutorにタスクを送信すると、それは次のように動作します。常に初期値なし、 workQueue.offer(task)LinkedBlockingQueueをします使用している場合

if (numberOfWorkingThreads < corePoolSize) { 
    startNewThreadAndRunTask(); 
} else if (workQueue.offer(task)) { 
    if (numberOfWorkingThreads == 0) { 
     startNewThreadAndRunTask(); 
    } 
} else if (numberOfWorkingThreads < maxPoolSize) 
    startNewThreadAndRunTask(); 
} else { 
    rejectTask(); 
} 
  • 結果として1つだけ スレッドが開始されました。
  • SynchronousQueue.offer(task)を呼び出すと、別のスレッドが を受け取るのを待っているときにのみ成功します。待機中の スレッドがないので、 時間ごとにfalseが返され、新しいスレッドが作成されます。
関連する問題