スレッドを使用する - Javaのマルチスレッド

スレッドを作成します。

、Runnableインタフェースを実装することにより、

class RunnableDemo implements Runnable {
    private String threadName;

    private RunnableDemo(String name) {
        this.threadName = name;
        System.out.println("creating thread:" + threadName);
    }

    @Override
    public void run() {
        System.out.println("Running " + threadName);

        try {
            for (int i = 0; i < 10; i++) {
                System.out.println("Thread:" + threadName + "," + i);
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("Thread " + threadName + "interrupter");
        }
        System.out.println("Thread " + threadName + " exiting");
    }
    // run
    public static void main(String[] args) {
        RunnableDemo r = new RunnableDemo("MyThread");
        r.run();
    }
}
复制代码

継承Threadクラス自体を通じ

public class ThreadDemo extends Thread {
    @Override
    public void run() {
        System.out.println("thread" + Thread.currentThread().getId() + " running...");
    }
    // run 10 thread
    public static void main(String[] args) throws InterruptedException {
        ThreadDemo[] threadDemos = new ThreadDemo[10];
        for (int i = 0; i < threadDemos.length; i++) {
            threadDemos[i] = new ThreadDemo();
        }
        for (ThreadDemo threadDemo : threadDemos) {
            threadDemo.start();
        }
        // wait other thread complete
        for (ThreadDemo threadDemo : threadDemos) {
            threadDemo.join();
        }
        System.out.println("completing");
    }
}
复制代码

スレッドを作成することによって達成呼び出し可能な(スレッドは、値の処理を返すことができます)

することによりFutureTask梱包Callableを通じて、インスタンスをThreadパッケージFutureTaskインスタンス、およびその後の呼び出し方法をThreadstart()

public class CallableDemo implements Callable {
    @Override
    public String call() throws Exception {
        return "yo!";
    }

    @Test
    public void callUse() throws Exception {
        CallableDemo callableDemo = new CallableDemo();
        System.out.println(callableDemo.call());
    }

    @Test
    public void threadUse() throws ExecutionException, InterruptedException {
        FutureTask futureTask= new FutureTask<>(new CallableDemo());
        Thread thread=new Thread(futureTask);
        thread.start();
        System.out.println(futureTask.get());
    }
}
复制代码

FutureTaskの継承

実行のスレッドプールのスレッド

スレッドプールを作成します。

一般的には、クラスThreadPoolExecutorを通じてスレッドを作成するには

ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                          int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler
                          )
复制代码
変数説明
  • 基本的なスレッドプールサイズcorePoolSize

  • スレッドプールの最大サイズmaximumPoolSize

  • 生存期間(スレッドの基本サイズを超えた)keepAliveTimeがアイドル状態のスレッド

  • ユニットアイドルスレッドの生存時間の単位(ミリ秒、秒...)

  • ワークキューのタスクキュー、ブロッキングキューを提出するタスク(BlockingQueue)。詳細:Javaのマルチスレッド-詳細なブロッキングキュー

  • デフォルトの実装があり、政策threadFactoryスレッド生産労働者、スレッドを作成し、カスタムスレッドファクトリを通じてスレッド情報を監視することができます

  • ハンドラ飽和戦略、スレッドタスクキューはいっぱい、または閉じたスレッドの処理に提出された課題であるため、

    • AbortPolicy、ポリシーを中断し、デフォルトのポリシーを、例外がスローされますRejectExecutionExceptionポリシーは、呼び出し側は、独自の例外処理コードを書くことができます

    • 例外をスローしない、静かに仕事を放棄し、戦略を放棄DiscardRunsPolicy

    • キュー最古動作します最長のミッション戦略を放棄DiscardOldestPolicy捨てられたタスクを(つまり、次が実行されます)。プライオリティキューは最も高い優先度になります

    • CallerRunsPolicy、発信者の実行ポリシー、実行する作業キューのスレッドを追加するためにスレッドを追加します

PS:参照テーブルのコンストラクタ

継承

スレッドプールを使用します

Runableインタフェース
public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService pool=Executors.newFixedThreadPool(2);
        pool.execute(() -> System.out.println("yo!"));
        pool.shutdown();
}
复制代码
呼び出し可能インターフェース

提出メソッドを呼び出すことにより、

ExecutorService過負荷提供submit()いずれかの受信方法Runnableインスタンスを受信することができCallableインスタンス。達成するためCallableのインタフェースクラスを、必要性の上書きcall()のみを通過して、メソッドを起動する方法の方法をExecutorServicesubmit()call()

public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService pool=Executors.newFixedThreadPool(2);
        Future future=pool.submit(() -> {
            Thread.sleep(100);
            return "yo!";
        });
        System.out.println(future.get());
        pool.shutdown();
}
复制代码
遅延タスクと定期的なタスクを使用します

定義:遅延タスク(「100ミリ秒の実行後のタスク」)、デューティ・サイクル(「10ms毎にタスクを実行します。」)

用途:新しいScheduledThreadPoolExector()オブジェクト

デモ:

public class ScheduleExecutorDemo implements Runnable {
    private String name;

    public ScheduleExecutorDemo(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + " 运行");
    }

    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService executorService1 = Executors.newScheduledThreadPool(2);
        // after 10s run
        executorService1.schedule(new ScheduleExecutorDemo("task1"), 10, TimeUnit.SECONDS);
        executorService1.shutdown();

        ScheduledExecutorService executorService2 = Executors.newScheduledThreadPool(2);
        // run per 1s
        executorService2.scheduleAtFixedRate(new ScheduleExecutorDemo("task1"), 
                0, 1, TimeUnit.SECONDS);
        // run per 2s
        executorService2.scheduleWithFixedDelay(new ScheduleExecutorDemo("task2"), 
                0, 2, TimeUnit.SECONDS);
    }
}
复制代码
使用のヒント

出典:アリババのJava開発マニュアル

  • スレッドのリソースは、スレッドプールによって提供されなければならないが、明示的にアプリケーションに独自のスレッドを作成することはできません。

    説明:スレッドプールを使用することの利点は、リソース不足の問題を解決するために、時間とシステムリソース消費スレッドを作成し、破壊にオーバーヘッドを削減することです。あなたがスレッドプールを使用しない場合、それはシステムが消費やメモリの問題「過度のハンドオーバを」リード類似した多数のスレッドを作成することがあります。

  • エグゼキュータ・スレッド・プールを作成することができますが、ThreadPoolExecutorの方法により、このアプローチは、学生が資源の枯渇の危険性を回避するために、プールの運用ルールを通すより明確に記述することができますされていません。

    説明:次のようにエグゼキュータ医療過誤スレッドプールオブジェクトが返されました:

    • FixedThreadPoolとSingleThreadPool:Integer.MAX_VALUEの許可要求キューの長さは、それによってOOMを引き起こす、多数の要求を蓄積してもよいです。

    • CachedThreadPoolとScheduledThreadPoolは:OOMを得、多数のスレッドを作成することができ、スレッドの数にInteger.MAX_VALUEを作成することを可能にします。

  • タイマーは、複数のTimeTaskを実行するときに、マルチスレッド並列処理タイミングタスクは、限り、1がスローされた例外をキャッチしないよう、他のタスクが自動的に終了します場合は、ScheduledExecutorServiceは問題ではありません使用します。

参考:

  1. JDK1.8.0ソース

  2. Javaのマルチスレッドとスレッドプールの呼び出し可能インタフェース

  3. 「戦闘でのJava並行処理。」

  4. 「Javaのマルチスレッドプログラミングの実用的なガイド(コア論文)」

おすすめ

転載: juejin.im/post/5d03a51e51882571521114fe