blog

JAVA 複数スレッドの連続実行を実現するいくつかの方法

方法1: Thread.join() 出力: 方法2: Thread.join() variant 出力: 方法3: CountDownLatch 出力: 方法4: スレッドプールの実装 出力: 方法...

Oct 30, 2023 · 4 min. read


方法1: Thread.join()

thread.join(): 続行する前に、threadの実行が完了するまで待つ。

public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"-a");
        }, "thread_1");
        Thread thread2 = new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"-aa");
        }, "thread_2");
        Thread thread3 = new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"-aaa");
        }, "thread_3");
    
        thread1.start();
        thread1.join();
        thread2.start();
        thread2.join();
        thread3.start();
        thread3.join();
    }
    

出力結果:

Thread_1-a
    Thread_2-aa
    Thread_3-aaa
    

方法2: Thread.join() のバリアント

スレッドクラスを抽出する

public class QueueThread extends Thread {
        private Thread preThread;
        private String text;
    
        QueueThread(Thread preThread, String str){
            this.preThread = preThread;
            this.str = text;
        }
    
        @Override
        public void run() {
            try {
                if (preThread != null) {
                    preThread.join();
                }
                System.out.println(Thread.currentThread().getName() + "-" + text);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    
        public static void main(String[] args) {
            OrderTread thread1 = new OrderTread(null, "a");
            OrderTread thread2 = new OrderTread(thread1, "aa");
            OrderTread thread3 = new OrderTread(thread2, "aaa");
    
            thread1.start();
            thread2.start();
            thread3.start();
        }
    
    }
    

出力:

Thread-0-a
    Thread-1-aa
    Thread-2-aaa
    

方法3: CountDownLatch

java.util.concurrent.CountDownLatchをの使用し1つのスレッド (または複数のスレッド) を実装し、他のスレッドが完了するまで待ってから実行します。

public static void main(String[] args) throws InterruptedException {
    
        final CountDownLatch countDownLatch = new CountDownLatch(2);
    
        System.out.println("スタート");
    
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "-" + "a");
            countDownLatch.countDown();
        }).start();
    
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "-" + "aa");
            countDownLatch.countDown();
        }).start();
    
        countDownLatch.await();
        System.out.println("終了");
    }
    

出力:

スタート
    Thread-0-a
    Thread-1-aa
    終了
    

方法4:スレッドプールで実装

単一スレッド プール + シーケンシャル キューにより、シーケンシャルな実行を保証します。 executorService.shutdown() は送信されたタスクを受け入れなくなりますが、キュー内のタスクは引き続き実行されます (shutdownNow()、awaitTermination() も同様)

public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 3; i++){
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "-" + i);
                }
            });
        }
        executorService.shutdown();
    }
    

出力:

pool-1-thread-1-0
    pool-1-thread-1-1
    pool-1-thread-1-2
    

方法5: CompletableFuture

1. CompletableFuture.runAsync() は future1.thenRun() と連携して順序を保証します 2. runAsync()+thenRun() は戻り値を受け入れることができません。戻り値は、supplyAsync()+thenApply() で指定できます。 3. 出力から、CompletableFuture によって使用されるデフォルトのスレッド プールが ForkJoinPool であることがわかります。 カスタムスレッドプールの受信もサポート

CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
System.out.print("");
}, Executors.newCachedThreadPool());
    
public static void main(String[] args) throws InterruptedException {
        CompletableFuture fu1 = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "-" + "a");
        });
        CompletableFuture fu2 = fu1.thenRun(()->{
            System.out.println(Thread.currentThread().getName() + "-" + "aa");
        });
        CompletableFuture fu3 = future2.thenRun(()->{
            System.out.println(Thread.currentThread().getName() + "-" + "aaa");
        });
    }
    

ソリューション

ForkJoinPool.commonPool-worker-1-a
    ForkJoinPool.commonPool-worker-1-aa
    main-aaa
    
Read next

ルーティング、モジュールルーティング

express ルートとは? Expressにおけるルートとは、クライアントのリクエストとサーバーのハンドラ関数のマッピング関係のことです。 Expressにおけるルートは、リクエストのタイプ、リクエストのURL、ルートオブジェクトの3つから構成されます。

Aug 19, 2023 · 2 min read