JavaスレッドプールThreadPoolExecutor(on)---理論

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, 
long keepAliveTime, TimeUnit unit, 
BlockingQueue workQueue, 
RejectedExecutionHandler handler) 

corePoolSize:最小数のスレッド、スレッドプール維持
maximumPoolSize:最大数のスレッド、スレッドプール維持
keepAliveTimeが:で許可さアイドル時間スレッドプール維持スレッド
単位単位で許可さ空き時間のスレッドプール維持スレッド
ワークキュー:バッファスレッドプールで使用キュー
ハンドラー:拒否されたタスクに対するスレッドプールの処理戦略

タスクはexecute(Runnable)メソッドを介してスレッドプールに追加されます。タスクはRunnableタイプのオブジェクトであり、タスクの実行メソッドはRunnableタイプのオブジェクトのrun()メソッドです。

execute(Runnable)メソッドを介してタスクをスレッドプールに追加する場合:

  1. この時点でスレッドプールの数がcorePoolSize未満の場合、スレッドプールのスレッドがアイドル状態であっても、追加されたタスクを処理するために新しいスレッドを作成する必要があります。
  2. この時点でスレッドプールの数がcorePoolSizeと等しいが、バッファーキューworkQueueがいっぱいでない場合、タスクはバッファーキューに入れられます。
  3. この時点でスレッドプールの数がcorePoolSizeより大きい場合、バッファーキューworkQueueがいっぱいであり、スレッドプールの数がmaximumPoolSizeより小さい場合は、追加されたタスクを処理するための新しいスレッドを作成します。
  4. スレッドプール内の数がcorePoolSizeより大きい場合、バッファーキューworkQueueがいっぱいであり、スレッドプール内の数がmaximumPoolSizeに等しい場合、タスクはハンドラーによって指定された戦略によって処理されます。

つまり、タスクの処理の優先順位は次のとおりです。

コアスレッドcorePoolSize、タスクキューworkQueue、最大スレッドmaximumPoolSize、3つすべてがいっぱいの場合は、ハンドラーを使用して拒否されたタスクを処理します。


スレッドプール内のスレッド数がcorePoolSizeより大きい場合、スレッドのアイドル時間がkeepAliveTimeを超えると、スレッドは終了します。このようにして、スレッドプールはプール内のスレッド数を動的に調整できます。


unitのオプションのパラメーターは、java.util.concurrent.TimeUnitのいくつかの静的属性です:
NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。

私が使用するworkQueueは次のとおりです。java.util.concurrent.ArrayBlockingQueue

ハンドラーには4つのオプションがあります。

  • ThreadPoolExecutor.AbortPolicy()

java.util.concurrent.RejectedExecutionExceptionをスローします

  • ThreadPoolExecutor.CallerRunsPolicy()

現在のタスクを追加してみてください。彼は自動的にexecute()メソッドを繰り返し呼び出します。

  • ThreadPoolExecutor.DiscardOldestPolicy()

古いタスクを放棄する

  • ThreadPoolExecutor.DiscardPolicy()

現在のタスクを放棄する

使用例:

package demo;

import java.io.Serializable;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThreadPool2
{
    
    
    private static int produceTaskSleepTime = 2;
    private static int produceTaskMaxNumber = 10;

    public static void main(String[] args)
    {
    
    
        // 构造一个线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
                new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 1; i <= produceTaskMaxNumber; i++)
        {
    
    
            try
            {
    
    
                // 产生一个任务,并将其加入到线程池
                String task = "task@ " + i;
                System.out.println("put " + task);
                threadPool.execute(new ThreadPoolTask(task));

                // 便于观察,等待一段时间
                Thread.sleep(produceTaskSleepTime);
            }
            catch (Exception e)
            {
    
    
                e.printStackTrace();
            }
        }
    }
}

/**
 * 线程池执行的任务
 */
class ThreadPoolTask implements Runnable, Serializable
{
    
    
    private static final long serialVersionUID = 0;
    private static int consumeTaskSleepTime = 2000;
    // 保存任务所需要的数据
    private Object threadPoolTaskData;

    ThreadPoolTask(Object tasks)
    {
    
    
        this.threadPoolTaskData = tasks;
    }

    public void run()
    {
    
    
        // 处理一个任务,这里的处理方式太简单了,仅仅是一个打印语句
        System.out.println(Thread.currentThread().getName());
        System.out.println("start .." + threadPoolTaskData);

        try
        {
    
    
            // //便于观察,等待一段时间
            Thread.sleep(consumeTaskSleepTime);
        }
        catch (Exception e)
        {
    
    
            e.printStackTrace();
        }
        threadPoolTaskData = null;
    }

    public Object getTask()
    {
    
    
        return this.threadPoolTaskData;
    }
}

説明:
1。このプログラムでは、タスクはRunnableタイプのオブジェクト、つまりThreadPoolTask​​タイプのオブジェクトです。
2.一般的に、タスクは処理方法に加えてデータを処理する必要があり、処理されたデータは構築方法を介してタスクに渡されます。
3.このプログラムでは、main()メソッドは残酷なリーダーに相当します。彼は多くのタスクを送信し、threadPoolと呼ばれる勤勉なチームにそれらを投げます。
このグループには少なくとも2人のメンバーがいます。2人が忙しすぎると、タスクはタスクリストに配置されます。
タスクが多すぎてタスクリストが大きすぎる(3を超える)場合は、新しいチームメンバーを雇って支援してください。ただし、コストを考慮すると、採用できないチームメンバーが多すぎて、最大4人のチームメンバーを採用できます。
4人のチームメンバーが忙しくて新しいタスクがある場合、チームはそれを処理できません。タスクは戦略によって処理されます。私たちの処理方法は、タスクが受け入れられるまでディスパッチを続けることです(もっと残酷です!ハハ)。
チームメンバーの作業はコストがかかるため、作業が非常にアイドル状態で、3SECONDSまで新しいタスクがない場合、一部のチームメンバーが解雇されます。ただし、チームの通常の運用では、作業がアイドル状態であっても、チームメンバーは2人以上になります。
4.produceTaskSleepTimeとconsumestTaskSleepTimeのサイズを調整して、タスクのディスパッチとタスクの処理の速度を制御することにより、これら2つの値を変更することにより、さまざまな速度でプログラムの動作条件を監視できます。
5. 4で参照したデータを調整し、さらにタスク破棄戦略を調整し、それを他の3つの戦略に置き換えることで、さまざまな戦略の下でさまざまな処理方法を確認できます。
6.その他の使用方法については、jdkのヘルプを参照してください。理解と使用が簡単です。

おすすめ

転載: blog.csdn.net/nikyae/article/details/111133970