2017-12-25 25 views
0

ThreadPoolExecutorクラスには、スレッドプールの最大サイズを指定するmaxPoolSizeクラスがあります。これは、スレッド数がその数より少ない場合、プール内のスレッドをすぐに実行する必要があることを意味します。しかし、私はそれが事実ではないことを発見した。実際にはcorePoolSizeを超えることはできません。私は混乱しています。何もしない場合、maxPoolSizeの目的は何ですか?ここに私のテストプログラムがあります:なぜThreadPoolExecutorのmaxPoolSizeは何もしませんか?

私はcorePoolSize = 2を指定しました。 maxPoolSize = 6;私は5つのスレッド(Runnable)を作成しました。私は5つのスレッド(Runnable)が同時に動くべきだと思った。しかし、彼らはそうではありません。それらのうちの2つだけが走っており、最初の2つが死ぬまで別の3つが脇に置かれています。

私はこのトピックについて多くの投稿を読んでいます。しかし、5つのスレッドを同時に実行させるためのガイドはありません。

import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.LinkedBlockingQueue; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 

public class MyThreadPoolExecutorTest2 
{ 
    private List<MyRunnable> myRunnables = new ArrayList<>(); 

    public static void main(String[] args) 
    { 
     new MyThreadPoolExecutorTest2().test(); 
    } 

    public void test() 
    { 
     int poolSize = 2; 
     int maxPoolSize = 6; 
     int threadPoolKeepAliveTimeInSec = 30; 
     ExecutorService threadPoolExecutor = 
       new MySimpleThreadPoolExecutor(poolSize, maxPoolSize, threadPoolKeepAliveTimeInSec); 
     int numOfThread = 5; 
     System.out.println("Start thread pool test with corePoolSize=" + poolSize + ", maxPoolSize=" + maxPoolSize 
       + ", actualThreads=" + numOfThread); 
     for (int i = 0; i < numOfThread; i++) 
     { 
      MyRunnable tempRunnable = new MyRunnable(i + 1, "PoolTest" + (i + 1)); 
      myRunnables.add(tempRunnable); 
      threadPoolExecutor.execute(tempRunnable); 
     } 
     System.out.println("********* wait for a while"); 
     try 
     { 
      Thread.sleep(20000); 
     } 
     catch (InterruptedException e) 
     { 
      e.printStackTrace(); 
     } 

     System.out.println("^^^^^^^^^^ shutdown them all"); 
     for (MyRunnable runnable : myRunnables) 
     { 
      runnable.shutdown(); 
     } 
     System.out.println("Ended thread pool test."); 
    } 

    public class MyRunnable implements Runnable 
    { 
     private int id = 0; 
     private String name = ""; 

     private boolean shutdown = false; 

     public MyRunnable(int id, String name) 
     { 
      this.id = id; 
      this.name = name; 
     } 

     @Override 
     public void run() 
     { 
      System.out.println("++++ Starting Thread: " + id + ":" + name); 
      while (!shutdown) 
      { 
       try 
       { 
        Thread.sleep(200); 
       } 
       catch (InterruptedException e) 
       { 
        e.printStackTrace(); 
       } 
      } 
      System.out.println("---- Ended Thread: " + id + ":" + name); 
     } 

     public void shutdown() 
     { 
      shutdown = true; 
     } 
    } 
} 

class MySimpleThreadPoolExecutor extends ThreadPoolExecutor 
{ 
    private static int peakActiveThreads = 0; 
    private String taskInfo = ""; 

    public MySimpleThreadPoolExecutor(int nThreads, int maxThreads, int threadPoolKeepAliveTimeInSec) 
    { 
     super(nThreads, maxThreads, threadPoolKeepAliveTimeInSec * 1000L, TimeUnit.MILLISECONDS, 
       new LinkedBlockingQueue<Runnable>()); 
     System.out.println("MySimpleThreadPoolExecutor::MySimpleThreadPoolExecutor(), threadPoolSize=" + nThreads 
       + ", maxThreadCount=" + maxThreads + ", threadPoolKeepAliveTimeInSec=" + threadPoolKeepAliveTimeInSec); 
    } 

    @Override 
    public void beforeExecute(Thread t, Runnable r) 
    { 
     int activeCount = getActiveCount(); 
     if (MySimpleThreadPoolExecutor.peakActiveThreads < activeCount) 
     { 
      MySimpleThreadPoolExecutor.peakActiveThreads = activeCount; 
     } 
     taskInfo = r.toString(); 
     String msg = 
       "BeforeE thread(name:id)::" + t.getName() + ":" + t.getId() + ", task::" + r.toString() + "\n" 
         + threadPoolInfoStr(); 
     System.out.println("ThreadInfo before, MySimpleThreadPoolExecutor::beforeExecute(), " + msg); 
     super.beforeExecute(t, r); 
    } 

    @Override 
    public void execute(Runnable command) 
    { 
     beforeExecute(Thread.currentThread(), command); 
     super.execute(command); 
    } 

    public String threadPoolInfoStr() 
    { 
     return String.format("Thead: %s/%d\n[PoolSize/CorePoolSize] [%d/%d]\nActive: %d\nCompleted: %d\nTask: %d" 
       + "\nisShutdown: %s\nisTerminated: %s\npeakActiveThreads: %d\nTaskInfo: %s\nQueueSize: %d", Thread 
       .currentThread().getName(), Thread.currentThread().getId(), getPoolSize(), getCorePoolSize(), 
       getActiveCount(), getCompletedTaskCount(), getTaskCount(), isShutdown(), isTerminated(), 
       MySimpleThreadPoolExecutor.peakActiveThreads, taskInfo, getQueue().size()); 
    } 
} 
+0

このスレッドは同様の問題について説明します。https://stackoverflow.com/questions/17659510/core-pool-size-vs-maximum-pool-size-in-threadpoolexecutor – Michael

答えて

1

さらに多くのスレッドは、キューがいっぱいの場合にのみ追加されます。

LinkedBlockingQueueは制限されていないので、決していっぱいになることはありません。したがって、プール内のスレッドのコア・プール・サイズを超えることはありません。

TransferQueueを使用するか、境界キューを使用してこれを修正してください。

関連する問題