多线程中的join方法

1. 有关线程的背景知识

当一个高优先级的线程到来时,无论低优先级的线程是否在运行,都将会被中断,腾出资源让高优先级的线程来执行。

2. 关于多线程中的几个重要的函数

了解多线程中的函数对于掌握多线程内部的状态转换非常重要,线程的状态转换过程可以参见另一篇博文http://blog.csdn.net/duxingxia_007/article/details/47009445。下面分别介绍这些会对线程状态产生影响的函数

2.1 join函数

join函数在jdk中的描述是

“阻塞调用线程,直到某个线程终止或经过了指定时间为止 。”

这里的问题是谁是调用线程,谁是某个线程?下面通过代码例子来说明。

public class JoinExample {
    public static void main(String[] args) throws InterruptedException {
        //任务1
        Thread t = new Thread(new Runnable() {
            public void run() {
                System.out.println("First task started");
                System.out.println("Sleeping for 2 seconds");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("First task completed");
            }
        });
        //任务2
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                System.out.println("Second task completed");
            }
        });

        t1.start();
        t.start(); 
        t.join(); //join作用区域
        System.out.println("main method run over");
    }
}

上面的代码中,当调用main方法开始执行的时候,总共会有三个线程启动,任务1、任务2、main方法所在的主线程。这里main方法所在的主线程是调用线程,某个线程是任务1线程。所以当执行上述代码时,main方法会阻塞,知道任务1执行完成后才结束。因此上述代码的执行结果中,main method run over会最后才打印出来。结果为:

Second task completed
First task started
Sleeping for 2 seconds
First task completed
main method run over

为了更加明显的对比,同时增强理解,当把t.join()这段代码注释掉后,main线程应该会很快结束,再不等到任务1和任务2结束的时候都结束了。执行的结果如下:

Second task completed
main method run over
First task started
Sleeping for 2 seconds
First task completed

也就是说t.join()之后的代码必须等到线程t执行完成之后才可以开始执行。为了验证这点,你可以尝试把t.start()移动到t.join()的后面,就会发现线程t1也会等到线程t执行完成后才会开始执行。就像下面这个样子:

public class JoinExample {
    public static void main(String[] args) throws InterruptedException {
        //任务1
        Thread t = new Thread(new Runnable() {
            public void run() {
                System.out.println("First task started");
                System.out.println("Sleeping for 2 seconds");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("First task completed");
            }
        });
        //任务2
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                System.out.println("Second task completed");
            }
        });


        t.start(); 
        t.join(); 
        t1.start();
        System.out.println("main method run over");
    }
}

执行的结果是:

First task started
Sleeping for 2 seconds
First task completed
main method run over
Second task completed

在这个过程中,main方法所在的线程经历的状态变化是:
开始-可执行-执行-阻塞-执行-结束
线程t1经历的状态变化是:
开始-可执行-执行-结束
这个join会在什么场景下使用呢?欢迎评论交流:)

2.2 yield函数

yield这个函数仅仅是当前线程放弃当前的时间片,把时间片腾出来,自己再回到可执行状态,等待JVM重新进行调度,重新调度时该线程当前就可能是第一个被拉出来进入到执行状态的线程。所以说,yield并不是一定把执行时间片留给其他的线程来执行,而是大家都回到了重新的起点等待被调度。需要记住的一点是,从运行状态进入到可运行状态时,当前线程持有的锁并不会被释放掉,仅仅是回到可运行状态,等待再次调度。
那么,执行这个yield方法又有什么用呢?

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值