精华内容
下载资源
问答
  • 多线程应用中,经常会遇到这种场景:后面的处理,依赖前面的N个线程的处理结果,必须等前面的线程执行完毕后,后面的代码才允许执行。在我不知道CyclicBarrier之前,最容易想到的就是放置一个公用的static变量,假如...

    多线程应用中,经常会遇到这种场景:后面的处理,依赖前面的N个线程的处理结果,必须等前面的线程执行完毕后,后面的代码才允许执行。

    在我不知道CyclicBarrier之前,最容易想到的就是放置一个公用的static变量,假如有10个线程,每个线程处理完上去累加下结果,然后后面用一个死循环(或类似线程阻塞的方法),去数这个结果,达到10个,说明大家都爽完了,可以进行后续的事情了,这个想法虽然土鳖,但是基本上跟语言无关,几乎所有主流编程语言都支持。package yjmyzz.test;

    public class ThreadLockTest {

    public static int flag = 0;//公用变量

    public static void main(String[] args) throws Exception {

    ThreadLockTest testObj = new ThreadLockTest();

    final int threadNum = 10;

    for (int i = 0; i 

    new Thread(new MyRunable(i, testObj)).start();

    }

    while (true) {

    if (testObj.flag >= threadNum) {

    System.out.println("-----------\n所有thread执行完成!");

    break;

    }

    Thread.sleep(10);

    }

    }

    static class MyRunable implements Runnable {

    int _i = 0;

    ThreadLockTest _test;

    public MyRunable(int i, ThreadLockTest test) {

    this._i = i;

    this._test = test;

    }

    @Override

    public void run() {

    try {

    Thread.sleep((long) (Math.random() * 10));

    System.out.println("thread " + _i + " done");

    //利用synchronized获得同步锁

    synchronized (_test) {

    _test.flag += 1;

    }

    System.out.println("thread " + _i + " => " + _test.flag);//测试用

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    }

    输出结果:

    thread 0 done

    thread 0 => 1

    thread 9 done

    thread 9 => 2

    thread 1 done

    thread 1 => 3

    thread 3 done

    thread 3 => 4

    thread 7 done

    thread 7 => 5

    thread 6 done

    thread 6 => 6

    thread 2 done

    thread 2 => 7

    thread 4 done

    thread 4 => 8

    thread 8 done

    thread 8 => 9

    thread 5 done

    thread 5 => 10

    -----------

    所有thread执行完成!

    除了这个方法,还可以借助FutureTask,达到类似的效果,其get方法会阻塞线程,等到该异步处理完成。缺点就是,FutureTask调用的是Callable,必须要有返回值,所以就算你不想要返回值,也得返回点啥package yjmyzz.test;

    import java.util.concurrent.Callable;

    import java.util.concurrent.ExecutionException;

    import java.util.concurrent.FutureTask;

    public class FutureTaskTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

    FutureTask[] tasks = new FutureTask[10];

    for (int i = 0; i 

    final int j = i;

    tasks[i] = new FutureTask(new Callable() {

    @Override

    public String call() throws Exception {

    Thread.sleep((long) (Math.random() * 100));

    return "task" + j + " done";

    }

    });

    new Thread(tasks[i]).start();

    }

    for (int i = 0; i 

    System.out.println(tasks[i].get());//依次等待所有task执行完毕

    }

    System.out.println("-----------\n所有task执行完成!");

    }

    }

    执行结果:

    task0 done

    task1 done

    task2 done

    task3 done

    task4 done

    task5 done

    task6 done

    task7 done

    task8 done

    task9 done

    -----------

    所有task执行完成!

    此外,Thread的Join方法也可以实现类似的效果,主要代码如下:public static void main(String[] args) throws Exception {

    final int threadNum = 10;

    Thread[] threads = new Thread[threadNum];

    for (int i = 0; i 

    threads[i] = new Thread(new MyRunable(i));

    threads[i].start();

    }

    for (int i = 0; i 

    threads[i].join();

    }

    System.out.println("-----------\n所有thread执行完成!");

    }

    当然,这个需求最“正统”的解法应该是使用CyclicBarrier,它可以设置一个所谓的“屏障点”(或称集合点),好比在一项团队活动中,每个人都是一个线程,但是规定某一项任务开始前,所有人必须先到达集合点,集合完成后,才能继续后面的任务。package yjmyzz.test;

    import java.util.concurrent.CyclicBarrier;

    public class ThreadTest {

    public static void main(String[] args) throws Exception {

    final int threadNum = 10;

    CyclicBarrier cb = new CyclicBarrier(threadNum + 1);//注意:10个子线程 + 1个主线程

    for (int i = 0; i 

    new Thread(new MyRunable(cb, i)).start();

    }

    cb.await();

    System.out.println("-----------\n所有thread执行完成!");

    }

    static class MyRunable implements Runnable {

    CyclicBarrier _cb;

    int _i = 0;

    public MyRunable(CyclicBarrier cb, int i) {

    this._cb = cb;

    this._i = i;

    }

    @Override

    public void run() {

    try {

    Thread.sleep((long) (Math.random() * 100));

    System.out.println("thread " + _i + " done,正在等候其它线程完成...");

    _cb.await();

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    }

    thread 9 done,正在等候其它线程完成...

    thread 5 done,正在等候其它线程完成...

    thread 0 done,正在等候其它线程完成...

    thread 6 done,正在等候其它线程完成...

    thread 4 done,正在等候其它线程完成...

    thread 2 done,正在等候其它线程完成...

    thread 3 done,正在等候其它线程完成...

    thread 8 done,正在等候其它线程完成...

    thread 7 done,正在等候其它线程完成...

    thread 1 done,正在等候其它线程完成...

    -----------

    所有thread执行完成!

    展开全文
  • 当然这个睡眠时间是主观的时间,是我们自己定的,这个方法不推荐,但是在这里还是写一下,毕竟是解决方法方法二:Thread的join()方法等待所有的子线程执行完毕,主线程在执行,thread.join()把指定的线程加入到当前...

    方法一:用sleep方法

    让主线程睡眠一段时间,当然这个睡眠时间是主观的时间,是我们自己定的,这个方法不推荐,但是在这里还是写一下,毕竟是解决方法

    71aba958c02c46b7de3d4b092427be17.png

    方法二:Thread的join()方法

    等待所有的子线程执行完毕,主线程在执行,thread.join()把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

    95a4f8b70efe9df2d0e47832cfa65277.png

    方法三:等待多线程完成的CountDownLatch

    注意:countDownLatch不可能重新初始化或者修改CountDownLatch对象内部计数器的值,一个线程调用countdown方法happen-before另外一个线程调用await方法

    7bd5ad2b799cdb6ca4fd4ec89235521b.png

    方法四:同步屏障CyclicBarrier

    5f5bc1fe2c384dda112819df8456031a.png

    方法五:线程池

    比如 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

    fixedThreadPool.shutdown();while (true) {//等待所有任务都执行结束

    if (fixedThreadPool.isTerminated()) {//所有的子线程都结束了

    System.out.println("共耗时:"+(System.currentTimeMillis()-startTime)/1000.0+"s");break;

    }

    }

    注意:countDownLatch和cyclicBarrier有什么区别?

    countDownLatch只能使用一次,而CyclicBarrier方法可以使用reset()方法重置,所以CyclicBarrier方法可以能处理更为复杂的业务场景。

    我曾经在网上看到一个关于countDownLatch和cyclicBarrier的形象比喻,就是在百米赛跑的比赛中若使用 countDownLatch的话冲过终点线一个人就给评委发送一个人的成绩,10个人比赛发送10次,如果用CyclicBarrier,则只在最后一个人冲过终点线的时候发送所有人的数据,仅仅发送一次,这就是区别。

    展开全文
  • 主线程中代码:longtStart=System.currentTimeMillis();System.out.println(Thread.currentThread().getName()+"开始");//打印开始标记for(intii=0;...}while(true){//等待所有子线程执行完if(!Im...

    主线程中代码:

    longtStart = System.currentTimeMillis();

    System.out.println(Thread.currentThread().getName() +"开始");//打印开始标记

    for(intii =0; ii 

    Thread t =newImportThread();

    t.start();

    }

    while(true){//等待所有子线程执行完

    if(!ImportThread.hasThreadRunning()){

    break;

    }

    Thread.sleep(500);

    }

    System.out.println(Thread.currentThread().getName() +"结束.");//打印结束标记

    longtEnd = System.currentTimeMillis();

    System.out.println("总共用时:"+ (tEnd - tStart) +"millions");

    long tStart = System.currentTimeMillis();

    System.out.println(Thread.currentThread().getName() + "开始");//打印开始标记

    for (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程

    Thread t = new ImportThread();

    t.start();

    }

    while(true){//等待所有子线程执行完

    if(!ImportThread.hasThreadRunning()){

    break;

    }

    Thread.sleep(500);

    }

    System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记

    long tEnd = System.currentTimeMillis();

    System.out.println("总共用时:"+ (tEnd - tStart) + "millions");

    打印的结果是:

    main开始

    Thread-1开始...

    Thread-5开始...

    Thread-0开始...

    Thread-2开始...

    Thread-3开始...

    Thread-4开始...

    Thread-5结束.

    Thread-4结束.

    Thread-2结束.

    Thread-0结束.

    Thread-3结束.

    Thread-1结束.

    main结束.

    总共用时:20860millions

    可以看到main线程是等所有子线程全部执行完后才开始执行的。

    ==================================================以下为第二次编辑===============================================

    上面的方法有一个隐患:如果线程1开始并且结束了,而其他线程还没有开始此时runningThreads的size也为0,主线程会以为所有线程都执行完了。解决办法是用一个非简单类型的计数器来取代List型的runningThreads,并且在线程创建之前就应该设定好计数器的值。

    MyCountDown类

    publicclassMyCountDown {

    privateintcount;

    publicMyCountDown(intcount){

    this.count = count;

    }

    publicsynchronizedvoidcountDown(){

    count--;

    }

    publicsynchronizedbooleanhasNext(){

    return(count >0);

    }

    publicintgetCount() {

    returncount;

    }

    publicvoidsetCount(intcount) {

    this.count = count;

    }

    }

    42/4<1234>

    展开全文
  • Java等待线程执行完毕

    千次阅读 2017-07-18 23:10:27
    前言:前一段时间在做项目的时候,某段代码中用到了多线程,该处代码需要开启多个线程,待这几个线程执行完毕后再接着执行后续的流程。现将可采用的方法记录如下。 要达到上述的描述的情形,可以使用Thread的join()...

    前言:前一段时间在做项目的时候,某段代码中用到了多线程,该处代码需要开启多个线程,待这几个线程执行完毕后再接着执行后续的流程。现将可采用的方法记录如下。


    要达到上述的描述的情形,可以使用Thread的join()方法,也可以使用java.util.concurrent包中的CountDownLatch类。具体如下:

    一、使用Thread.join()方法

    该方法在JDK API中的解释为“等待该线程终止”,存在三个方法重载,如下:
    void join();
    void join(long millis); // 等待该线程终止的最长时间为millis毫秒
    void join(long millis, int nanos); // 等待该线程终止的最长时间为millis毫秒+nanos纳秒

    代码如下:

    package threadTest;
    
    import java.util.Vector;
    import java.util.concurrent.*;
    
    /**
     * Created by worm0527 on 2017/7/17.
     */
    public class ThreadTest extends Thread {
    
        // 线程名称
        private String threadName;
    
        // 线程休眠时间
        private int sleepSec;
    
        ThreadTest(String threadName, int sleepSec) {
            super(threadName);
            this.sleepSec = sleepSec;
            start();// 在构造方法中启动线程
        }
    
        @Override
        public void run() {
            long starttime = System.currentTimeMillis();
            System.out.println(Thread.currentThread().getName() + " running...");
            try {
                // 休眠制定时间(单位:秒)
                TimeUnit.SECONDS.sleep(sleepSec);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " run at " + (System.currentTimeMillis() - starttime) + " ms");
        }
    
        public static void main(String[] args) throws InterruptedException {
    
            long starttime = System.currentTimeMillis();
            System.out.println("Thread main running...");
    
            Vector<Thread> threadVector = new Vector<Thread>();
            for (int i = 1; i < 5; i++) { // 开启四个线程
                Thread t = new ThreadTest("Thread" + i, i);
                threadVector.add(t);
            }
    
            for (Thread t : threadVector) { // 循环调用线程join()方法,等待线程结束
                t.join();
            }
    
            System.out.println("Thread main End");
            System.out.println("Thread main run at " + (System.currentTimeMillis() - starttime) + " ms");
        }
    }
    

    运行结果:

    运行结果

    二、使用CountDownLatch类

    主要使用了该类的await()和countDown()两个方法。await()阻塞线程,直到计数器归零或者线程被中断,调用countDown()来递减计数器。

    代码如下:

    package threadTest;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by worm0527 on 2017/7/18.
     */
    public class ThreadTest1 extends Thread {
    
        // 线程名称
        private String threadName;
    
        // 线程休眠时间
        private int sleepSec;
    
        private CountDownLatch latch; // 线程类中持有CountDownLatch对象的引用
    
        public ThreadTest1(String threadName, int sleepSec, CountDownLatch latch) {
            super(threadName);
            this.sleepSec = sleepSec;
            this.latch = latch;
            start();// 在构造方法中启动线程
        }
    
        @Override
        public void run() {
            long starttime = System.currentTimeMillis();
            System.out.println(Thread.currentThread().getName() + " running...");
            try {
                // 休眠制定时间(单位:秒)
                TimeUnit.SECONDS.sleep(sleepSec);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " run at " + (System.currentTimeMillis() - starttime) + " ms");
            latch.countDown();
        }
    
        public static void main(String[] args) throws InterruptedException {
    
            long starttime = System.currentTimeMillis();
            System.out.println("Thread main running...");
    
            CountDownLatch latch = new CountDownLatch(4); // 共四个子线程
            for (int i = 1; i < 5; i++) {
                new ThreadTest1("Thread" + i, i, latch);
            }
            latch.await(); // 阻塞,直到线程计数归零
    
            System.out.println("Thread main End");
            System.out.println("Thread main run at " + (System.currentTimeMillis() - starttime) + " ms");
        }
    
    }
    

    运行结果:

    运行结果

    展开全文
  • 简单总结两种实现方式: 一、应用 Callable();二、利用计数器 egg: 一、应用 Callable() ...ExecutorService executorService ...// ......// 等待 更新线程更新完再落地..."线程执行完毕!" ) ; // 执行后续程序
  • java 等待所有线程执行完毕

    千次阅读 2017-01-22 16:34:55
    问题的由来主线程等待所有线程都运行完后,再执行逻辑,这个需求很普遍。比如,在处理数据时,为了效率期间,起了10个线程,分别处理一块数据,这样能缩短处理时间,10个线程执行完后,继续进行下边的逻辑(有点...
  • 最近项目中用到线程框架,需要主线程等待所有子线程执行完毕,小编突发奇想,结合设计模式中的复合模式和装饰模式写了这个deamo,这个例子最大的特点是,它不但可以实现最基本的需求,它还拥有像junit一样灵活的使用...
  • Java多线程--让主线程等待线程执行完毕 使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待java.util.concurrent....
  • 常用的两种方式: 第一种方式:来自大神... } catch (InterruptedException E) { // handle } 然后在线程方法中加入: try { ... } catch (Exception e) { e.printStackTrace(); }finally { countDownLatch.countDown(); }
  • 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!1.接力前面在《“全栈2019”Java多线...
  • 使用Java多线程编程时经常遇到主线程需要等待线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待java.util.concurrent.CountDownLatch使用countDownLatch.await()方法非常简单的完成主线...
  • 执行前面所有的线程后再执行后续逻辑 代码如下: WorkThread.java public class WorkThread extends Thread { @Override public void run() { try { System.out.println(getName() + &amp;quot;run...
  • 在实际开发过过程中,我们会经常...待所有子线程的任务完成之后,在运行后续的业务,或者退出Main线程。代码如下:WorkThread.javapublic class WorkThread extends Thread { @Override public void run() { try {
  • java 等待线程/线程池执行完毕

    千次阅读 2017-08-07 15:43:54
    1.单线程开始并执行完毕线程开始后,需要用到join的方法 不废话直接贴代码 public static void main(String args[]) { long begin = System.currentTimeMillis(); System.out.println(begin); Thread thread...
  • * 主线程等待其他线程执行完毕 */ public class WhileTrueThread{ public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch=new CountDownLatch(3);
  • 创建一批Java线程,然后这批Java线程几乎同时全部跑起来,但是有些开发场景下,开发者需要等到这些Java线程全部执行完毕后,才去执行接下去的业务流程。这个时候就可以CountDownLatch就可以派上用场,CountDownLatch...
  • 使用Java多线程编程时经常遇到主线程需要等待线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待。 CountDownLatch是一个同步辅助工具,用于使一个或多个线程等待(即阻塞)知道一组在...
  • 原文出处:...问题:如何实现 java 主线程等待线程执行完毕之后再执行? 工作总往往会遇到异步去执行某段逻辑,
  • join用于让当前执行线程等待join线程执行结束。其实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远wait,直到join线程中止后,线程的this.notifyAll会被调用 JDK不推荐在线程实例上使用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,440
精华内容 576
关键字:

java等待线程执行完毕

java 订阅