JAVAは、マルチスレッドとThreadPoolExecutorスレッドプールコンテンツの4つの方法を実装し、7つのパラメーター拒否戦略の詳細な説明カスタムスレッドプール

JAVAマルチスレッドの4つの方法でのスレッドプールの詳細な分析

JAVAマルチスレッド4つの方法

javaでスレッドを実装する4つの方法:

  • 1. Threadクラスを継承し、runメソッドをオーバーライドします
  • 2. Runnableインターフェイスを実装し、runメソッドを実装します
  • 3. Callableインターフェイスを継承してcallメソッドを実装し、futureTaskを使用して呼び出します(戻り値付き/例外を処理できます)

[上記の3つのタイプは通常のビジネスコードでは使用されません。]

[すべてのマルチスレッド非同期タスクは、実行のためにスレッドプールに引き渡される必要があります]

  • 4.スレッドプール(スレッドの再利用、同時実行の最大数の制御、スレッドの管理)

    • リソース消費を削減する

      • すでに作成されたスレッドを再利用することにより、スレッドの作成と破棄によって引き起こされる損失を減らします
    • 応答速度を向上させる

      • スレッドプール内のスレッド数が上限を超えていないため、一部のスレッドはタスクの割り当てを待機している状態であり、タスクが来ると、新しいスレッドを作成せずに実行できます。
    • スレッドの管理性を向上させる

      • スレッドプールは、現在のシステムの特性に応じてプール内のスレッドを最適化し、スレッドの作成と破棄によって発生するシステムオーバーヘッドを削減します。スレッドのワイヤレス作成と破棄は、システムリソースを削減するだけでなく、システムの安定性も低下させ、均一性のためにスレッドプールを使用します。分布

1. Threadクラスを継承し、runメソッドをオーバーライドします

public class ThreadTest {
    
    
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
//        1.继承Thread类 重写run方法
        new Thread01().start();
        System.out.println("main end ....");
    }
    public static class Thread01 extends  Thread{
    
    
        @Override
        public void run() {
    
    
            System.out.println("1.继承Thread类 重写run方法");
        }
    }
}

2. Runnableインターフェイスを実装し、runメソッドを実装します

public class ThreadTest {
    
    
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
//         2.实现Runnable接口 实现run方法
        new Thread(new Runnable01()).start();
        System.out.println("main end ....");
    }
    public static class Runnable01 implements  Runnable{
    
    
        @Override
        public void run() {
    
    
            System.out.println("2.实现Runnable接口 实现run方法");
        }
    }
}

3. Callableインターフェイスを継承してcallメソッドを実装し、futureTaskを使用して呼び出します(戻り値付き/例外を処理できます)

public class ThreadTest {
    
    
    public  static void main(String args[]) throws ExecutionException, InterruptedException {
    
    
        System.out.println("main start ....");
//        3.继承Callable接口 实现call方法 使用futureTask调用  (有返回值/可处理异常)
        Callable01 callable01 = new Callable01();
        FutureTask<Integer> futureTask = new FutureTask<>(callable01);
        new Thread(futureTask).start();
        //使用futureTask 获取返回值  会阻塞等待
        System.out.println(futureTask.get());
        System.out.println("main end ....");
    }
    public static class Callable01 implements Callable<Integer>{
    
    

        @Override
        public Integer call() throws Exception {
    
    
            System.out.println("3.继承Callable接口 实现call方法 使用futureTask调用  (有返回值/可处理异常)");
            return new Integer(200);
        }
    }
}

4.スレッドプール

4.1基本的なスレッドプールの適用

public class ThreadTest {
    
    
    //正常情况保证一个项目中只有少数线程池,每个异步任务,线程池让他自己取执行
    //Executors.newFixedThreadPool(10); 使用工具类生成容量为10的线程池
    //自定义线程池使用  new ThreadPoolExecutor();  自定义七大参数
    public static ExecutorService service = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
        try{
    
    
            service.execute(()->{
    
    
                System.out.println("4.线程池");
            });
        }catch (Exception e){
    
    
                e.printStackTrace();
        }finally{
    
    
            service.shutdown();
        }
        System.out.println("main end ....");
    }

}

4.2実行者補助ツール

Executors.newFixedThreadPool(int);  //创建固定容量的线程池
Executors.newSingleThreadExecutor();  //创建一个只有1个工作线程的线程池
Executors.newCachedThreadPool() //创建一个可扩容的线程池。执行很多短期异步任务,线程池根据需要创建新线程,但在先前构造的线程可用时将重用他们。可扩容。
public class MyThreadPoolDemo {
    
    
    public  static void main(String args[]){
    
    
        //固定容量的线程池
//        ExecutorService threadPool =Executors.newFixedThreadPool(5); //创建一个有5个工作线程的线程池
//        ExecutorService threadPool =Executors.newSingleThreadExecutor(); //创建一个只有1个工作线程的线程池
        ExecutorService threadPool =Executors.newCachedThreadPool();  //创建一个可扩容的线程池
        try{
    
    
            for (int i = 1; i <10; i++) {
    
    
                //从线程池中使用一个工作线程
                threadPool.execute(()->{
    
    
                    System.out.println(Thread.currentThread().getName());
                });
            }
        }catch (Exception e){
    
    

        }finally{
    
    
            //任务结束 归还线程
            threadPool.shutdown();
        }
    }
}

上記の3つのExecutorsAPI最下層は、異なるパラメーターを持つThreadPoolExecutorを使用して実装されます。
ここに写真の説明を挿入

4.3ThreadPoolExecutorの7つのパラメーターの分析

ここに写真の説明を挿入

  • 1.corePoolSize:スレッド内の常駐コアスレッドの数

  • 2、maxmunPoolSize:スレッドプールで同時に実行できるスレッドの最大数。この値は1より大きくなければなりません。

  • 3. KeepAliveTime:冗長なアイドルスレッドの存続時間。現在のプール内のスレッドの数がcorePoolSize &&を超え、アイドル時間がkeepAliveTimeに達すると、corePoolSizeスレッドが残るまで、余分なスレッドは破棄されます(過剰な戦略)

  • 4.ユニット:keepAliveTimeユニット

  • 5. workQueue:タスクブロッキングキュー、送信されたがまだ実行されていないタスク(十分な戦略がない)

  • 6、threadFactory:スレッドプールでワーカースレッドを生成するスレッドファクトリを表し、スレッドの作成に使用されます。通常、デフォルトで問題ありません

  • 7.ハンドラー:拒否戦略。これは、タスクブロッキングキューがいっぱいで、作業スレッドの総数がスレッドプール内のスレッドの最大数(maxmunPoolSize)以上の場合に、実行を要求された実行可能戦略(完全戦略)を拒否する方法を意味します。

4.4ThreadPoolExecutorの動作原理

  • 1.スレッドプールを作成した後、リクエストの待機を開始します。

  • 2. execute()メソッドを呼び出して要求タスクを追加すると、スレッドプールは次の判断を下します。

    2.1実行中のスレッドの数がcorePoolSize未満の場合は、すぐにこのタスクを実行するスレッドを作成します。

    2.2実行中のスレッドの数がcorePoolSize以上の場合、タスクをキューに入れます。

    2.3この時点でキューがいっぱいで、実行中のスレッドの数がまだmaximumPoolSize未満の場合でも、このタスクをすぐに実行するには、非コアスレッドを作成する必要があります。

    2.4キューがいっぱいで、実行中のスレッドの数がmaximumPoolSize以上の場合、スレッドプールは飽和拒否戦略を開始して実行します。

  • 3.スレッドがタスクを完了すると、実行のためにキューから次のタスクが削除されます。

  • 4.スレッドが一定期間(keepAliveTime)を超えて何の関係もない場合、スレッドは次のように判断します。
    現在実行中のスレッドの数がcorePoolSizeより大きい場合、このスレッドは停止します。
    したがって、スレッドプールのすべてのタスクが完了すると、最終的にはcorePoolSizeのサイズに縮小されます。

4.5カスタムスレッドプール

7つのパラメーターを使用してスレッドプールをカスタマイズします(最も重要なパラメーターは拒否戦略です)

public class MyThreadPoolDemo {
    
    
    public  static void main(String args[]){
    
    
       ExecutorService threadPool = new ThreadPoolExecutor(2,
                5,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

4つの主要な拒否戦略:

1. ThreadPoolExecutor.AbortPolicy(); RejectExecutionExceptionを直接スローして、システムが正常に実行されないようにします。

2. ThreadPoolExecutor.CallerRunsPolicy();呼び出し元は調整メカニズムを実行します。この戦略は、タスクを放棄したり例外をスローしたりすることはありませんが、特定のタスクを呼び出し元に返すため、新しいタスクのフローが減少します。

3. ThreadPoolExecutor.DiscardOldestPolicy();キュー内で最も長く待機しているタスクを破棄してから、現在のタスクをキューに追加して、現在のタスクの送信を再試行します

4. ThreadPoolExecutor.DiscardPolicy();この戦略は、処理できないタスクをサイレントに破棄するか、タスクを処理しないか、例外をスローします。タスクが失われることが許されている場合、これが最善の戦略です。

メカニズム、この戦略はタスクを放棄したり例外をスローしたりすることはありませんが、特定のタスクを呼び出し元に返すため、新しいタスクのフローが減少します

3. ThreadPoolExecutor.DiscardOldestPolicy();キュー内で最も長く待機しているタスクを破棄してから、現在のタスクをキューに追加して、現在のタスクの送信を再試行します

4. ThreadPoolExecutor.DiscardPolicy();この戦略は、処理できないタスクをサイレントに破棄するか、タスクを処理しないか、例外をスローします。タスクが失われることが許されている場合、これが最善の戦略です。

おすすめ

転載: blog.csdn.net/weixin_44634197/article/details/108345736