多个线程等待

2019-05-31  本文已影响0人  麦兜的夏天

场景一:

假设在一个线程 A 中开启了另一个线程 B,A 线程依赖 B 线程的计算结果,可是直接开启线程后,很有可能 A 线程比 B 线程跑得快,也就是说还没等 B 线程计算出结果,A 线程已经结束了。

public static void main(String[] args) throws Exception {
        Thread parser1 = new Thread(new Runnable() {
            @Override
            public void run() {
                temp temp = new temp();  //temp 对象的 a 属性初始化值为 0
                temp.a += 100;
                System.out.println("parser1 finish");
            }
        });
        parser1.start();
        
        temp temp = new temp();
        System.out.println(temp.a);       
} 

//main 函数属于一个线程,它内部开启了 parser1 这个线程。
打印出的结果是 0 ,而不是 100 。

怎么解决这个问题?
让线程 A 等待着线程 B,直到线程 B 结束之后再继续进行。 只需要在线程 B 开启之后,再调用 join() 方法阻塞线程,就可以了。

public static void main(String[] args) throws Exception {
        Thread parser1 = new Thread(new Runnable() {
            @Override
            public void run() {
                temp temp = new temp();
                temp.a += 100;
                System.out.println("parser1 finish");
            }
        });
        parser1.start();
        parser1.join();  //阻塞线程
        
        temp temp = new temp();
        System.out.println(temp.a);       
} 

打印的结果为 100

场景二:

假如在线程 A 里面有 B、C 这几个线程,A 依赖于 B 和 C 线程的执行结果,并且 B 和 C 之间也有某种联系,只有当 B 和 C 在某个固定的点上同步执行,它们才能默契的完成任务。


两个线程之间的关系.png
    public static void main(String[] args) throws Exception {
        //temp 对象的静态变量 a 初始值等于 0
        //如果第一个线程先执行,那么 a 就等于 1
        //这时候再执行第二个线程,a 会变成 100;
        //如果它们的执行顺序正好相反,那么 a 就变成 1 了。
        Thread parser1 = new Thread(new Runnable() {
            @Override
            public void run() {
                temp temp = new temp();
                temp.a += 1;

                try {
                    System.out.println("线程一其余代码被执行");
                    Thread.sleep(5000L);
                    System.out.println("线程一执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread parser2 = new Thread(new Runnable() {
            @Override
            public void run() {
                temp temp = new temp();
                temp.a *= 100;

                try {
                    System.out.println("线程二其余代码被执行");
                    Thread.sleep(5000L);
                    System.out.println("线程二执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
     
    }
    public static void main(String[] args) throws Exception {
        Thread parser1 = new Thread(new Runnable() {
            @Override
            public void run() {
                temp temp = new temp();
                temp.a += 1;

                try {
                    System.out.println("线程一其余代码被执行");
                    Thread.sleep(5000L);
                    System.out.println("线程一执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread parser2 = new Thread(new Runnable() {
            @Override
            public void run() {
                temp temp = new temp();
                temp.a *= 100;

                try {
                    System.out.println("线程二其余代码被执行");
                    Thread.sleep(5000L);
                    System.out.println("线程二执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //parser1 和 parser2 之间是平等的竞争关系,哪个先执行不一定,所以让第二个线程等待1秒
        parser1.start();
        parser2.start();
        parser1.join();
        parser2.join(1000L);
        System.out.println(new temp().a);       
    }
    
//执行结果
线程一其余代码被执行
线程二其余代码被执行
线程一执行结束  
线程二执行结束
(。。。。经历漫长的等待之后。。。。)
100   
    static CountDownLatch c = new CountDownLatch(2);   
    //构造函数中传入参数作为计数器,如果想要等待N个点完成,就传入N

    public static void main(String[] args) throws Exception {
        Thread parser1 = new Thread(new Runnable() {
            @Override
            public void run() {
                temp temp = new temp();
                temp.a += 1;
                c.countDown();    //计数器减一

                try {
                    System.out.println("线程一其余代码被执行");
                    Thread.sleep(5000L);
                    System.out.println("线程一执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread parser2 = new Thread(new Runnable() {
            @Override
            public void run() {
                temp temp = new temp();
                c.countDown();   //计数器减二
                temp.a *= 100;

                try {
                    System.out.println("线程二其余代码被执行");
                    Thread.sleep(5000L);
                    System.out.println("线程二执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });

        parser1.start();
        parser2.start();

        c.await();   //计数器等于0时,不再阻塞当前线程

        System.out.println(new temp().a);
    }
    
//执行结果
线程二其余代码被执行
线程一其余代码被执行
100
(。。。。经历漫长的等待之后。。。。)
线程二执行结束
线程一执行结束  
上一篇下一篇

猜你喜欢

热点阅读