Java Thread.join方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chennai1101/article/details/84745253

1. Thread.join方法

join方法会等待指定线程结束,然后才会继续运行。

public class ThreadJoin {

    public static void main(String[] args) {
        try {
            ThreadA threadA = new ThreadA();
            threadA.start();

            System.out.println("In Main begin at " + System.currentTimeMillis());
            threadA.join();
            System.out.println("In Main end at " + System.currentTimeMillis());
        } catch (InterruptedException e) {
        }
    }

    static class ThreadA extends Thread {
        public void run() {
            try {
                System.out.println("In ThreadA begin at " + System.currentTimeMillis());
                Thread.sleep(3000);
                System.out.println("In ThreadA end at " + System.currentTimeMillis());
            } catch (InterruptedException e) {
            }
        }
    }

}

输出

In Main begin at 1543394291551
In ThreadA begin at 1543394291551
In ThreadA end at 1543394294551
In Main end at 1543394294551

2. join(long)方法

join(long)方法会等待指定线程一段时间,然后进入运行状态。

将上面的threadA.join()修改成以下代码,

threadA.join(2000);

输出

In Main begin at 1543394637246
In ThreadA begin at 1543394637246
In Main end at 1543394639247
In ThreadA end at 1543394640247

如果是等待4秒,在3秒时就返回并结束程序。

3. join方法解析

join方法会调用join(0),而join(long)在源码里如此实现。

public final void join() throws InterruptedException {
    join(0);
}

public final synchronized void join(long millis)
throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

如果millis为0,直接调用wait(0),否则在等待指定时间后返回。而Thread结束线程后,会调用唤醒所有等待列表中的线程。

public class ThreadFinishWait {

    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        threadA.start();

        new ThreadB(threadA).start();
        new ThreadB(threadA).start();
    }

    static class ThreadA extends Thread {

        public void run() {
            try {
                System.out.println("In ThreadA begin at " + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println("In ThreadA end at " + System.currentTimeMillis());
            } catch (InterruptedException e) {
            }
        }
    }

    static class ThreadB extends Thread {
        ThreadA threadA;

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

        public void run() {
            synchronized (threadA) {
                try {
                    System.out.println("In ThreadB begin at " + System.currentTimeMillis());
                    threadA.wait();
                    System.out.println("In ThreadB end at " + System.currentTimeMillis());
                } catch (InterruptedException e) {
                }
            }
        }
    }
}

输出

In ThreadA begin at 1543395597963
In ThreadB begin at 1543395597963
In ThreadB begin at 1543395597964
In ThreadA end at 1543395599963
In ThreadB end at 1543395599963
In ThreadB end at 1543395599963

join方法中调用了线程的wait方法,因此要小心对线程对象锁的使用,以免造成一些意外。

public class ThreadJoinError {

    public static void main(String[] args) {
        try {
            ThreadA threadA = new ThreadA();
            threadA.start();

            ThreadB threadB = new ThreadB(threadA);
            threadB.start();

            System.out.println("In Main begin at " + System.currentTimeMillis());
            threadA.join();
            System.out.println("In Main end at " + System.currentTimeMillis());
        } catch (InterruptedException e) {
        }
    }

    static class ThreadA extends Thread {
        public void run() {
            try {
                System.out.println("In ThreadA begin at " + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println("In ThreadA end at " + System.currentTimeMillis());
            } catch (InterruptedException e) {
            }
        }
    }

    static class ThreadB extends Thread {
        ThreadA threadA;

        ThreadB(ThreadA threadA) {
            this.threadA = threadA;
        }

        public void run() {
            synchronized (threadA) {
                try {
                    System.out.println("In ThreadB begin at " + System.currentTimeMillis());
                    Thread.sleep(5000);
                    System.out.println("In ThreadB end at " + System.currentTimeMillis());
                } catch (InterruptedException e) {
                }
            }
        }
    }

}

输出

扫描二维码关注公众号,回复: 4340633 查看本文章
In ThreadA begin at 1543396791415
In Main begin at 1543396791415
In ThreadB begin at 1543396791415
In ThreadA end at 1543396793415
In ThreadB end at 1543396796416
In Main end at 1543396796416

线程ThreadB获取了ThreadA的线程锁,join方法需要等待ThreadB释放线程锁后才能完成执行。

猜你喜欢

转载自blog.csdn.net/chennai1101/article/details/84745253