ThreadPoolExecutorソースコード学習(1)-コア属性とアプリケーション

Executorsクラスでは、jdkは使用できる4つのスレッドプールを提供します。つまり、
newCachedThreadPool:
corePoolSizeは0、作成できるスレッドの最大数はInteger.MAX_VALUE
newScheduledThreadPool:
作成できるスレッドの最大数はInteger.MAX_VALUEです。
newFixedThreadPool:
タスクキューは、最大の長さにInteger.MAX_VALUEであることができます
:newSingleThreadExecutor
タスクキューに許可される最大長はInteger.MAX_VALUEであります

これらの4つは、Alibaba Java開発仕様では推奨されていません。これらの4つのスレッドプールでは、スレッドの最大数が制限されていないか、ブロッキングキューが制限されておらず、OOMが発生する可能性があるためです。

カスタムスレッドプールを使用することをお勧めします。これにより、スレッドの最大数、キューのブロック、拒否戦略などを合理的に制御できます。

ThreadPoolExecutorにはいくつかの重要な属性があります

カスタムスレッドプール

private static void customThreadPool() {
    
    
        ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        try {
    
    
            for (int i = 0; i < 90; i++) {
    
    
                threadPool.execute(() -> {
    
    
                    System.out.println(Thread.currentThread().getName() + "\t 开始处理业务");
                });
            }

        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            threadPool.shutdown();
        }
    }

パラメータの説明

コア属性

int corePoolSize:核心线程数
int maximumPoolSize:允许创建的最大线程数
long keepAliveTime:空闲时间
TimeUnit unit:时间单位
BlockingQueue<Runnable> workQueue:任务队列
ThreadFactory threadFactory:线程池工厂
RejectedExecutionHandler handler:拒绝策略

对于一个线程池来说,允许有 maximumPoolSize + workQueue.length 个任务提交过来,超过了这个阈值,就会触发拒绝策略

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
这个遍历的高三位保存的是线程池的状态,后29位保存的是线程池中工作线程的数量

スレッドプールのステータス

/**
     * 运行状态,线程池刚创建就是这个状态
     * 高三位是111,低29位是0
     * 该状态会接收新的任务请求
     * 也会处理在阻塞队列中等待处理的任务
     */
    private static final int RUNNING    = -1 << COUNT_BITS;
    /**
     * 停工状态,不再接收新任务,但是会处理已经在执行的和阻塞队列中的任务
     * 高三位为000,低29位为0,
     * 在running状态调用线程池的shutdown()方法,会从running变更为shutdown
     */
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    /**
     * 停止状态,不再接收新任务,已有的任务也会中断,阻塞队列中的任务也不会再运行
     * 高三位为001,低29位为0
     *         在调用shutdownnow()方法之后,会从running/shutdown变更为stop状态
     */
    private static final int STOP       =  1 << COUNT_BITS;
    /**
     * 清空状态,所有任务都停止了,工作的线程也全部结束了,workerCount为0
     * 高三位为010,低29位为0
     * 为此状态时,还将调用terminated()方法
     */
    private static final int TIDYING    =  2 << COUNT_BITS;
    /**
     * 终止状态,线程池已经销毁;为此状态时还将调用terminated()方法
     * 高三位为100,低29位为0
     */
    private static final int TERMINATED =  3 << COUNT_BITS;

拒否戦略:

1、AbortPolicy:直接抛出异常 RejectedExecutionException
2、CallerRunsPolicy:在调用方线程中执行任务
3、DiscardOldestPolicy:丢弃最先进入到队列中的任务,调用的是queue.offer()方法
4、DiscardPolicy:不做任务处理,其实丢弃的是当前任务

動作原理

    1. 创建线程池,等待请求过来
    2. 当调用了execute()方法添加一个请求任务之后,线程池会做如下判断:

    3. 1. 如果当前运行的线程数小于corePoolSize,那么会创建线程,运行这个任务
       2. 如果正在运行的线程数量大于或者等于corePoolSize,那么将这个任务加入队列
       3. 如果队列也满了,这时候运行的线程数还小于maximumPoolSize,就会创建非核心线程来运行这个任务
       4. 如果队列满了,且正在运行的线程数达到了maximumPoolSize,那么线程池会启动拒绝策略来执行

    4. 当一个线程的任务结束之后,会从队列中取下一个任务来执行
    5. 当一个线程空闲时间超过了keepAliveTime时,线程池会做以下判断:
    6. 如果当前运行的线程数超过了corePoolSize时,那么这个线程会被销毁,线程池中所有任务结束以后,线程数量会缩减到corePoolSize的大小

実行と送信の違い

1.
入力パラメーターが異なります。executeの入力パラメーターはRunnableのみで、submitの入力パラメーターはRunnableまたはcallableです。2。Submitには戻り値があり、submitの最下層はexecuteとも呼ばれます。 executeが呼び出されると、入力が入力されます。パラメーターはRunnableFuture
3.submitにパッケージ化され、例外処理を容易にします。タスクが例外をスローした場合、future.get()によって例外情報をキャプチャできます。

コアメソッド

ここに画像の説明を挿入

1. Executorはスレッドプールの基本インターフェイスであり、executeメソッドは1つだけです
。2。ExecutorServiceはスレッドプールExecutorインターフェイスのサブインターフェイスであり、スレッドプールで他の操作(送信、シャットダウンなど)を追加で提供します
。3 。AbstractExecutorService抽象クラス。次のようなインターフェースのexecutorService部分を実装します
。submit4.ThreadPoolExecutorはAbstractExecutorServiceを継承します。

スレッドプールのステータス、ワーカースレッドの数を取得します

/**
     * 获取当前线程池的状态
     * @param c
     * @return
     */
    private static int runStateOf(int c)     {
    
     return c & ~CAPACITY; }

    /**
     * 获取线程池活跃的数量
     * @param c
     * @return
     */
    private static int workerCountOf(int c)  {
    
     return c & CAPACITY; }

    /**
     * 获取运行状态和活动线程数量的值
     * @param rs
     * @param wc
     * @return
     */
    private static int ctlOf(int rs, int wc) {
    
     return rs | wc; }

runWorker()

送信されたタスクを実行します。これがコアメソッドです。このメソッドでは、
現在送信されているタスクが最初
実行され、キューに入れられたタスクがタスクキューから取得
され、タスクが実行されます。

getTask()

これは、タスクキューからキューに入れられたタスクを取得する方法です。新しいスレッドが追加されると、現在送信されているタスクが最初に実行されます。タスクが実行されると、タスクキューからキューに入れられたタスクを取得して実行しようとします。順番に。

おすすめ

転載: blog.csdn.net/CPLASF_/article/details/110489886