【问题标题】:How to make the main wait for all threads to complete如何让主线程等待所有线程完成
【发布时间】:2016-09-14 08:56:20
【问题描述】:

我有一个程序,我在其中创建了 10 个线程来运行。我希望主线程等到一切都完成后再完成。我正在尝试使用 .join 命令,但它似乎不起作用。此外,我正在尝试显示所有线程的运行时,但它无法正常工作。下面是我的代码。

//File: CohanThread.java
//Author: Ryan A. Cohan
//Date: August 4, 2016
//Purpose: To create, run, and analyze a thread based program. IOBound runs IO intensive
//operations in the form of printing 1000 times to the console. CPUBound runs CPU
//intensive operations by computing an equation and printing 1000 times.

package cohanthread;

import java.text.*;

public class CohanThread{

    public static void main(String args[]) throws InterruptedException{
        NumberFormat formatter = new DecimalFormat("#0.00000");

        IOBound io1 = new IOBound();
        IOBound io2 = new IOBound();
        IOBound io3 = new IOBound();
        IOBound io4 = new IOBound();
        IOBound io5 = new IOBound();

        CPUBound cpu1 = new CPUBound();
        CPUBound cpu2 = new CPUBound();
        CPUBound cpu3 = new CPUBound();
        CPUBound cpu4 = new CPUBound();
        CPUBound cpu5 = new CPUBound();

        long scheduleStart = System.currentTimeMillis();
        io1.start();
        io2.join();
        io3.join();
        io4.join();
        io5.join();
        cpu1.join();
        cpu2.join();
        cpu3.join();
        cpu4.join();
        cpu5.join();
        long scheduleEnd = System.currentTimeMillis();
        System.out.println("Runtime of all threads: " + formatter.format((scheduleEnd - scheduleStart) / 1000d));
        System.out.println("Processes complete.");
    }
}

class IOBound extends Thread{
    NumberFormat formatter = new DecimalFormat("#0.00000");
    @Override
    public void run(){
        long start = System.currentTimeMillis();
        for(int i = 0; i < 1000; i++){
            System.out.println("Thread number is: " + i);
        }
        long end = System.currentTimeMillis();
        System.out.println("IO Thread runtime: " + formatter.format((end - start) / 1000d));
    }
}

class CPUBound extends Thread{
    NumberFormat formatter = new DecimalFormat("#0.00000");
    @Override
    public void run(){
        String binary = "";
        long start = System.currentTimeMillis();
        for(int i = 0; i < 1000; i++){
            while(i > 0){
                int remainder = i % 2;
                binary = remainder + binary;
                i = i / 2;
            }
            System.out.println("Binary number: " + binary);
            long end = System.currentTimeMillis();
            System.out.println("CPU Thread runtime: " + formatter.format((end - start) / 1000d));
        }
    }
}

【问题讨论】:

  • “它似乎不起作用” --- join() 按规定工作。
  • 您要加入未启动的线程?除此之外:“它不起作用”不是一个充分的错误描述。请提供您的预期与您观察到的对比。
  • 您启动一个线程并加入除您实际启动的线程之外的所有其他线程..

标签: java multithreading wait


【解决方案1】:

join 不启动计算,必须启动所有线程并使用 join 等待完成...

https://docs.oracle.com/javase/tutorial/essential/concurrency/join.html

使用这个主......

public static void main(String args[]) throws InterruptedException{
    NumberFormat formatter = new DecimalFormat("#0.00000");

    IOBound io1 = new IOBound();
    IOBound io2 = new IOBound();
    IOBound io3 = new IOBound();
    IOBound io4 = new IOBound();
    IOBound io5 = new IOBound();

    CPUBound cpu1 = new CPUBound();
    CPUBound cpu2 = new CPUBound();
    CPUBound cpu3 = new CPUBound();
    CPUBound cpu4 = new CPUBound();
    CPUBound cpu5 = new CPUBound();

    long scheduleStart = System.currentTimeMillis();
    io1.start();
    io2.start();
    io3.start();
    io4.start();
    io5.start();
    cpu1.start();
    cpu2.start();
    cpu3.start();
    cpu4.start();
    cpu5.start();


    io1.join();
    io2.join();
    io3.join();
    io4.join();
    io5.join();
    cpu1.join();
    cpu2.join();
    cpu3.join();
    cpu4.join();
    cpu5.join();
    long scheduleEnd = System.currentTimeMillis();
    System.out.println("Runtime of all threads: " + formatter.format((scheduleEnd - scheduleStart) / 1000d));
    System.out.println("Processes complete.");
}

【讨论】:

  • 这就像一个魅力。我不知道我在想什么没有初始化所有线程。非常感谢。
【解决方案2】:

你可以使用 java java.util.concurrent 包;

public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        List<Future<?>> futureList = new ArrayList<>();
        futureList.add(executor.submit(new IOBound()));
        futureList.add(executor.submit(new IOBound()));
        futureList.add(executor.submit(new IOBound()));
        futureList.add(executor.submit(new IOBound()));
        futureList.add(executor.submit(new IOBound()));

        futureList.add(executor.submit(new CPUBound()));
        futureList.add(executor.submit(new CPUBound()));
        futureList.add(executor.submit(new CPUBound()));
        futureList.add(executor.submit(new CPUBound()));
        futureList.add(executor.submit(new CPUBound()));

        for (Future future:futureList) {
            try {
                //this method will blocking until task finished
                future.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

【讨论】:

    【解决方案3】:

    ExecutorService 是要走的路!!

    您可以在此处使用执行器服务和要执行的线程列表。

    我已更新程序以使用 Executor Service。

    import java.text.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class CohanThread{
    
        public static void main(String args[]) throws InterruptedException{
            NumberFormat formatter = new DecimalFormat("#0.00000");
    
            ExecutorService es = Executors.newFixedThreadPool(5);
            List<Callable<Object>> threadList = new ArrayList<Callable<Object>>();
    
            IOBound io1 = new IOBound();
            IOBound io2 = new IOBound();
            IOBound io3 = new IOBound();
            IOBound io4 = new IOBound();
            IOBound io5 = new IOBound();
            threadList.add(Executors.callable(io1));
            threadList.add(Executors.callable(io2));
            threadList.add(Executors.callable(io3));
            threadList.add(Executors.callable(io4));
            threadList.add(Executors.callable(io5));
    
            CPUBound cpu1 = new CPUBound();
            CPUBound cpu2 = new CPUBound();
            CPUBound cpu3 = new CPUBound();
            CPUBound cpu4 = new CPUBound();
            CPUBound cpu5 = new CPUBound();
            threadList.add(Executors.callable(cpu1));
            threadList.add(Executors.callable(cpu2));
            threadList.add(Executors.callable(cpu3));
            threadList.add(Executors.callable(cpu4));
            threadList.add(Executors.callable(cpu5));
    
            long scheduleStart = System.currentTimeMillis();
            List<Future<Object>> results = es.invokeAll(threadList);
            long scheduleEnd = System.currentTimeMillis();
            System.out.println("Runtime of all threads: " + formatter.format((scheduleEnd - scheduleStart) / 1000d));
            System.out.println("Processes complete.");
        }
    }
    
    class IOBound extends Thread{
        NumberFormat formatter = new DecimalFormat("#0.00000");
        @Override
        public void run(){
            long start = System.currentTimeMillis();
            for(int i = 0; i < 1000; i++){
                System.out.println("Thread number is: " + i);
            }
            long end = System.currentTimeMillis();
            System.out.println("IO Thread runtime: " + formatter.format((end - start) / 1000d));
        }
    }
    
    class CPUBound extends Thread{
        NumberFormat formatter = new DecimalFormat("#0.00000");
        @Override
        public void run(){
            String binary = "";
            long start = System.currentTimeMillis();
            for(int i = 0; i < 1000; i++){
                while(i > 0){
                    int remainder = i % 2;
                    binary = remainder + binary;
                    i = i / 2;
                }
                System.out.println("Binary number: " + binary);
                long end = System.currentTimeMillis();
                System.out.println("CPU Thread runtime: " + formatter.format((end - start) / 1000d));
            }
        }
    }
    

    注意List&lt;Future&lt;Object&gt;&gt; answers = es.invokeAll(threadList); 会一直等到所有线程都执行完毕。

    希望对您有所帮助。祝编码愉快!

    【讨论】:

      猜你喜欢
      • 2012-07-22
      • 2014-10-05
      • 2020-09-21
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 2010-12-26
      • 2016-04-11
      • 1970-01-01
      相关资源
      最近更新 更多