目次
スレッド プールの利点
如何触发拒绝策略和线程池扩容?
ホームページ Java &#&チュートリアル Javaスレッドプールを作成する方法

Javaスレッドプールを作成する方法

May 16, 2023 am 08:43 AM
java

スレッド プールの利点

  • スレッドの再利用を実現し、スレッドの再作成や破棄を回避できます。スレッドの作成と破棄は、CPU にとって非常に負荷がかかります。

  • 作成できるスレッドの最大数を制限し、マシンのパフォーマンスに応じてスレッド プールのパラメーターを動的に調整して、アプリケーションのパフォーマンスを向上させることができます。

  • スケジュール実行や同時実行制御などの機能を提供します。

  • #スレッドの統合管理。

スレッド プールを作成する 5 つの方法

1: キャッシュ スレッド プール (非推奨)

2: 固定容量のスレッド プール (非推奨)

3: シングル スレッド プール (推奨されません)

4: スケジュールされたタスクのスレッド プール (推奨されません)

5: ThreadPoolExecutor 構築メソッド (開発された) を使用してスレッド プールを作成しますAlibaba のマニュアルを強くお勧めします)

スレッド プールを作成する最初の 4 つの方法はすべて、Executor の静的メソッドを通じて作成されます。

キャッシュ スレッド プール CachedThreadPool

	ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            final int finalI = i;
            executorService.execute(new Runnable() {
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);
                }
            });
        }
ログイン後にコピー

キャッシュ スレッド プールが推奨されないのはなぜですか?

ソース コード分析

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());
    }
ログイン後にコピー
 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
    }
ログイン後にコピー

上記の 2 つのコード スニペットから、CachedThreadPool の MaximumPoolSize が整数の最大値 2147483647 であることがわかります。これは、無制限のスレッド作成とスレッドの作成に相当します。メモリが必要です。はい、これによりメモリ オーバーフローが発生します。通常のマシンでは、これほど大量のスレッドを作成するためにそれほど大きなメモリを使用することはありません。

固定容量スレッド プールFixedThreadPool

newFixedThreadPool(int num)、num は指定する固定スレッドの数です

	ExecutorService executorService = Executors.newFixedThreadPool(5);

      for (int i = 0; i < 10; i++) {
          final int finalI = i;
          executorService.execute(new Runnable() {
              public void run() {
                  System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);
              }
          });
      }
ログイン後にコピー

出力:

pool-1-thread-5run>4

pool-1-thread-4run>3
pool-1-thread-5 run> 5
pool-1-thread-3run>2
pool-1-thread-3run>8
pool-1-thread-3< thread- >run>9
pool-1-thread-2run>1
pool-1-thread-1run>0
pool-1- thread- 5run>7
pool-1-thread-4run>6

スレッドの再利用が実現されていることがわかります。

FixedThreadPool が固定スレッド プールであるのはなぜですか?

ソース コード分析

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
    }
ログイン後にコピー

このソース コードから、コア スレッドの数 (corePoolSize) と最大スレッド数 (maximumPoolSize) が両方とも nThread であることがわかります。この場合、スレッド プールは拡張されず、スレッドの数は固定されます。

シングル スレッド プール SingleThreadExecutor

	ExecutorService executorService = Executors.newSingleThreadExecutor();

      for (int i = 0; i < 10; i++) {
          final int finalI = i;
          executorService.execute(new Runnable() {
              public void run() {
                  System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);
              }
          });

      }
ログイン後にコピー

SingleThreadExecutor にはスレッドが 1 つしか含まれていないのはなぜですか?

ソース コード分析

public static ExecutorService newSingleThreadExecutor() {
        return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));
    }
ログイン後にコピー

このソース コードから、コア スレッド数 (corePoolSize) と最大スレッド数 (maximumPoolSize) が両方とも 1 であることがわかります。 1つのスレッド。

Scheduled ThreadPool

	  int initDelay=10; //初始化延时
      int period=1;//初始化延迟过了之后,每秒的延时

      ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);

      scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
          @Override
          public void run() {
              System.out.println(Thread.currentThread().getName()+"<thread->run>");
          }
      },initDelay,period, TimeUnit.SECONDS);
ログイン後にコピー

このコードの効果は、プログラムの実行後 10 秒待機し、最初の結果を出力し、その後 1 秒ごとに結果を出力することです。

なぜ ScheduledThreadPool が推奨されないのですか?

ソースコード解析

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, 2147483647, 10L, TimeUnit.MILLISECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue());
    }
ログイン後にコピー

ScheduledThreadPoolの最大スレッド数(maximumPoolSize)は整数の最大値2147483647となっており、これはスレッドを無制限に作成することと同等であることがわかります。スレッドはメモリを必要とするため、メモリ オーバーフローが発生します。通常のマシンでは、これほど多くのスレッドを作成するためにそれほど大きなメモリを使用することはありません。

ThreadPoolExecutor はスレッド プールを作成します (強く推奨)

	ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20,
              2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),
              Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

      for (int i = 0; i < 12; i++) {
          final int finalI = i;
          threadPoolExecutor.execute(new Runnable() {
              public void run() {
                  System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);
              }
          });
      }
ログイン後にコピー

ThreadPoolExecutor の 7 つのパラメータの詳細な説明
	public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        
    }
ログイン後にコピー
  • corePoolSize: コア スレッドの数。これらのスレッドは一度作成されると破棄されず、常に存在します。スレッド プールにはデフォルトではスレッドがありません。タスクが到着すると、ThreadFactory を通じてスレッドが作成され、常に存在します。

  • maximumPoolSize: スレッドの最大数。非コア スレッドの数 = minimumPoolSize-corePoolSize. 非コア スレッドの数は、実際にはスケーラブル スレッドの数であり、破棄される可能性があります。

  • keepAliveTime: 非コア スレッドのアイドル状態の生存時間。拡張によって生成された非コア スレッドの数が keepAliveTime 後もアイドル状態のままである場合、これらの非コア スレッドは破棄されます。

  • unit: keepAliveTime の時間単位 (例: 秒)

  • workQueue: 待機エリア。 >corePoolSize のタスクが来ると、そのタスクは workQueue のブロッキング キューに格納され、他のスレッドが処理するのを待ちます。

  • threadFactory: スレッド ファクトリ。スレッドを作成する方法。

  • ハンドラー: 拒否戦略。 >最大スレッド数 workQueue の容量に達すると、拒否ポリシー

workQueue
ArrayBlockingQueue: 境界付きブロッキング キューが実行されます。キューにはサイズ制限があり、容量を超えると、拡張または拒否ポリシーがトリガーされます。

	public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }
ログイン後にコピー

LinkedBlockingQueue: 無制限のブロッキング キュー。キューにはサイズ制限がないため、メモリ オーバーフローが発生する可能性があります。

	 public LinkedBlockingQueue() {
        this(2147483647);
    }
ログイン後にコピー

handler
AbortPolicy: 例外を直接スローします。

	public static class AbortPolicy implements RejectedExecutionHandler {
        public AbortPolicy() {
        }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString());
        }
    }
ログイン後にコピー

DiscardPolicy: 操作は実行されません。タスクをサイレントに破棄します

	public static class DiscardPolicy implements RejectedExecutionHandler {
        public DiscardPolicy() {
        }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
ログイン後にコピー

DiscardOldestPolicy: 最長の既存タスクを破棄します

	public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() {
        }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }

        }
    }
ログイン後にコピー

CallerRunsPolicy: タスクを送信したスレッドにタスクを処理させます

	public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public CallerRunsPolicy() {
        }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }

        }
    }
ログイン後にコピー

threadFactory

	ThreadFactory threadFactory = Executors.defaultThreadFactory();

      threadFactory.newThread(new Runnable() {
          @Override
          public void run() {
              System.out.println("threadFactory");
          }
      }).start();
ログイン後にコピー
如何触发拒绝策略和线程池扩容?
	ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20,
              2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),
              Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

      for (int i = 0; i < 26; i++) { //并发数26
          final int finalI = i;
          threadPoolExecutor.execute(new Runnable() {
              public void run() {
                  System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);
              }
          });
      }
      /**
       * 核心线程数=10,最大线程数=20,故可扩容线程数=20-10
       * BlockingQueue的大小为5,故等待区的大小为5,也就是当并发数<=核心线程数+5不会扩容,并发数大于16才会扩容
       *
       * 触发扩容:并发数>核心线程数+阻塞队列的大小
       * 对于这段代码,如果来了26个并发,10个并发会被核心线程处理,5个会在等待区,剩下11个会因为等待区满了而触发扩容
       * 因为这里最多能够扩容10个,这里却是11个,所以会触发拒绝策略
       */
ログイン後にコピー
  • 为什么这段代码会触发拒绝策略

对于这段代码,如果来了26个并发,10个并发会被核心线程处理,5个会在等待区,剩下11个会因为等待区满了而触发扩容,但是又因为因为这里最多能够扩容10个,这里却是11个,所以会触发拒绝策略。

  • 怎么触发扩容

触发扩容:并发数>核心线程数(corePoolSize)+阻塞队列(workQueue)的大小

  • 使用Java纯手写一个线程池

以上がJavaスレッドプールを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

Spring Tool Suiteで最初のSpring Bootアプリケーションを実行するにはどうすればよいですか? Spring Tool Suiteで最初のSpring Bootアプリケーションを実行するにはどうすればよいですか? Feb 07, 2025 pm 12:11 PM

Spring Bootは、Java開発に革命をもたらす堅牢でスケーラブルな、生産対応のJavaアプリケーションの作成を簡素化します。 スプリングエコシステムに固有の「構成に関する慣習」アプローチは、手動のセットアップを最小化します。

See all articles