Java多线程问题--join()的使用以及方法join()后面的代码提前运行的原因

本文内容部分引自《Java多线程编程核心技术》,感谢作者!!!

代码地址:https://github.com/xianzhixianzhixian/thread.git

join()方法的使用

1、join()方法的用途是使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。

2、join()和synchronized的区别:join()在内部使用的是wait()方法进行等待,而synchronized关键字使用的是“对象监视器”原理作为同步。join()执行后会立马释放锁,而synchronized则会持有锁直到运行结束。

3、在join的过程中,如果当前线程对象被中断,则当前线程出现java.lang.InterruptedException异常。

4、join(long)和sleep(long)的区别:join(long)的内部是由wait(long)实现的,所以join(long)争抢到锁执行后会立刻释放锁,而Thread.sleep(long)则会使线程睡眠long毫秒后执行完相应的代码后释放锁。

5、join(long)和Thread.start()在同一个代码块中时,join(long)大部分先运行。

join(long)后面的代码提前运行示例及原因

ThreadA.java

/**
 * @author: xianzhixianzhixian
 * @date: 2019-01-07 21:34
 */
public class ThreadA extends Thread {

    private ThreadB b;

    public ThreadA(ThreadB b) {
        this.b = b;
    }

    @Override
    public void run() {
        try {
            synchronized (b) {
                System.out.println("begin A ThreadName="+
                        Thread.currentThread().getName()+" "
                        +System.currentTimeMillis());
                Thread.sleep(5000);
                System.out.println("end A ThreadName="+
                        Thread.currentThread().getName()+" "
                        +System.currentTimeMillis());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ThreadB.java

/**
 * @author: xianzhixianzhixian
 * @date: 2019-01-07 21:34
 */
public class ThreadB extends Thread {
    @Override
    synchronized public void run() {
        try {
            System.out.println("begin B ThreadName="+
                    Thread.currentThread().getName()+" "
                    +System.currentTimeMillis());
            Thread.sleep(5000);
            System.out.println("end B ThreadName="+
                    Thread.currentThread().getName()+" "
                    +System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Run.java

/**
 * 方法join()后面的代码提前运行示例(有时会出现这种情况)
 * 这里涉及到join(long)和a、b线程争抢对象锁的问题
 * @author: xianzhixianzhixian
 * @date: 2019-01-07 21:38
 */
public class Run {
    public static void main(String[] args) {
        try {
            ThreadB b = new ThreadB();
            ThreadA a = new ThreadA(b);
            a.start();
            b.start();
            b.join(2000);
            System.out.println("main end "+System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果:

第一种情况:A线程运行完之后main中的语句执行完毕,B线程继续执行完毕

原因:

1、 b.join(2000)方法先抢到B锁, 然后将B锁进行释放;

2、ThreadA抢到锁,打印ThreadAbegin并且sleep(5000);

3、ThreadA打印ThreadA end, 并释放锁;

4、这时join(2000)和Tl订eadB争抢锁, 而join(2000)再次抢到锁, 发现时间已过, 释放锁后打印main end;

5、ThreadB抢到锁打印ThreadB begin;

6、5秒之后再打印ThreadBend。

Java多线程问题--join()的使用以及方法join()后面的代码提前运行的原因_第1张图片

第二种情况:A线程运行完之后,B线程继续执行完毕,main中的语句执行完毕

原因:

1、b.join(2000)方法先抢到B锁, 然后将B锁进行释放;

2、T比eadA抢到锁,打印TeadAbegin并且sleep(5000);

3、ThreadA打印T缸eadAend, 并释放锁;

4、这时join(2000)和ThreadB争抢锁,而ThreadB抢到锁后执行sleep(5000)后释放锁;

5、main end在最后输出。

Java多线程问题--join()的使用以及方法join()后面的代码提前运行的原因_第2张图片

第三种情况:实验不出来,截书上图吧

Java多线程问题--join()的使用以及方法join()后面的代码提前运行的原因_第3张图片

你可能感兴趣的:(Java,多线程)