スレッドプールの理解について簡単に説明します

6296 ワード

1、まずいくつかのインタフェースとクラスの関係から説明する必要があります.
extends   implements extends
Executor(インタフェース)-------->ExecutorService(インタフェース)-------->AbstractExecutorService(抽象クラス)-------->ThreadpolExecutor
(execute()) (submit())
2.ThreadPoolExecutor(ExecutorServiceのデフォルト実装クラス)に対する理解:
彼は4つの構造関数を持っています.
public class ThreadPoolExecutor extends AbstractExecutorService {
    .....
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
        BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
    ...
}
の中で最も4番目に完璧で、この構造関数のパラメータについて説明します.
corePoolSize:スレッドプールのサイズで、作成開始時にスレッドはありませんが、タスクがあるのを待ってスレッドの作成を開始するか、prestartAllCoreThreads()またはprestartCoreThread()メソッドでスレッドの作成を行うことができます.つまり、タスクが来る前にcorePoolSizeスレッドまたはスレッドを作成します.デフォルトでは、スレッドプールを作成した後、スレッドプールのスレッド数は0で、タスクが来た後、スレッドを作成してタスクを実行し、スレッドプールのスレッド数がcorePoolSizeに達した後、到着したタスクをキャッシュキューに配置します.
maxnumPoolSize:スレッドプールの最大拡張可能サイズ
keepAliveTime:スレッドがタスク実行されていない場合にどのくらいの時間で終了するかを示します.基本的には、スレッドプール内のスレッドがcorePoolSizeに達した後に考慮されます.
unit:keepAliveTimeの時間単位:day,hour,minutes,seconds,ms,nsなどがあります
workQueue:ブロックキューで、ArrayBlockingQueueとPriorityBlockingQueueがあり、LinkedBlockingQueueとSynchronousが一般的です.スレッドプールのキューポリシーはBlockingQueueに関連しています.
threadFactory:スレッドファクトリで、主にスレッドを作成するために使用されます.
handler:タスクの処理を拒否した場合のポリシーを示します.
次に、コンストラクション関数を使用したプログラミングを行います.
package threadPoll;

/**
 * Created by Administrator on 2015/11/2 0002.
 */
public class MyTask implements Runnable{
    int num;
    public MyTask(int num) {
        this.num=num;
    }

    public void run() {
        System.out.println("Is doing..task"+num);
        try{
            Thread.currentThread().sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("task"+num+" is done.");
    }
}

テストクラス
package threadPoll;

import java.util.concurrent.*;

/**
 * Created by Administrator on 2015/11/2 0002.
 */
public class MyTest {
    public static void main(String[] args) {
        ThreadPoolExecutor pool=new ThreadPoolExecutor(5,8,200, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5));
        for(int i=0;i<15;i++){
            MyTask myTask=new MyTask(i);
            pool.execute(myTask);
            System.out.println("now threadcorepoolsize is "+pool.getPoolSize()
                + ", cachepoolsize is" +pool.getQueue().size()
                +",is completedsize is"+pool.getCompletedTaskCount());
    }
        pool.shutdown();
    }
}

スレッド数がスレッドプールの最大スレッド数より大きい場合は、キャッシュ領域に配置できます.まだ足りない場合は、待機します.
以下でよく使用される3つの方法は、コンストラクション関数によって定義されているため、コンストラクション関数の代わりに使用できます.
新SingleThreadExecutor:単一スレッドのスレッドプールを作成します.このスレッドプールでは、1つのスレッドのみが動作します.つまり、1つのスレッドがすべてのタスクをシリアルで実行することに相当します.この唯一のスレッドが異常に終了した場合、新しいスレッドが置き換えられます.このスレッドプールは、すべてのタスクの実行順序がタスクのコミット順序で実行されることを保証します.
新FixedThreadPool:固定サイズのスレッドプールを作成します.タスクをコミットするたびに、スレッドがスレッドプールの最大サイズに達するまでスレッドが作成されます.スレッドプールのサイズは、最大値に達すると変更されず、実行異常によってスレッドが終了すると、スレッドプールに新しいスレッドが追加されます.
新CachedThreadPool:サイズ:Integer.MAX_VALUEはキャッシュ可能なスレッドプールを作成します.スレッドプールのサイズがタスクの処理に必要なスレッドを超えると、空き(60秒でタスクを実行しない)のスレッドの一部が回収され、タスク数が増加すると、このスレッドプールはスマートに新しいスレッドを追加してタスクを処理することができます.このスレッドプールはスレッドプールのサイズに制限はありません.スレッドプールのサイズは、オペレーティングシステム(またはJVM)が作成できる最大スレッドサイズに完全に依存します.
新ScheduledThreadPool:無限のサイズのスレッドプールを作成します.このスレッド・プールは、タイミングおよび周期的なタスク実行の要件をサポートします.
3つの静的アプローチの実装は、ThreadPoolExecutorのコンストラクション関数に基づいているが、与えられたバッファ・プールのサイズ、最大容量のサイズ、ブロック・キューの格納方法が異なる.
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

次に、3つの静的関数を使用してプログラミングを行います.
MyThreadクラスの定義:
package threadPool;

/**
 * Created by Administrator on 2015/11/2 0002.
 */
public class MyThread extends Thread {
    public void run(){
        System.out.println(Thread.currentThread().getName()+"  is doing...");
        try{
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

テストクラスを定義します.
package threadPool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by Administrator on 2015/11/2 0002.
 */
public class ThreadPool {
    public static void main(String[] args) {
        ExecutorService pool= Executors.newFixedThreadPool(2);
        //ExecutorService pool=Executors.newSingleThreadExecutor();
        Thread t1=new MyThread();
        Thread t2=new MyThread();
        Thread t3=new MyThread();
        Thread t4=new MyThread();

        pool.execute(t1);//         ,  newSingleThreadExecutor          ,
        // newFixThreadPool()             。
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);

        pool.shutdown();

    }
}