多线程之join方法带来的问题

join方法代码带来的问题:

显示一段有意思的代码:

public class TestWaitOne {

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(10000);
                System.out.println("thread starting..........");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
        try {
            thread.join();
            System.out.println("main starting.............");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

因为一行代码:

thread.join();

从而导致了主线程进入到了阻塞状态,直到线程thread执行完成,主线程才能够继续执行。那么原理是什么?

    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;
            }
        }
    }

wait(有参)和wait()的区别

wait()无参,是直接让当前的线程进入到阻塞状态,然后需要别的线程进行notify() || notifyAll()来进行唤醒,才可以继续来进行抢锁;

wait(有参),这里做一个区分,如果参数是0,那么就表示等待0秒之后,然后才会有继续去获取得到锁对象;那么也就是说wait(0)就是和wait()是一样的效果。

参考连接:

http://bbs.itheima.com/thread-311354-1-1.html

wait(有参),如果参数大于0,那么标识的是等待了多少秒之后,然后才继续去获取得到锁对象;这里不是可以直接获取得到锁的,而是还需要继续排队获取得到锁;

和Thread.sleep(long)的区别

Thread.sleep在执行期间,是不会释放锁的,继续持有锁。而wait是会释放锁的。

那么来代码来演示一下:

参数为0:

public class TestWaitOne {

    public static void main(String[] args) {
        Object obj = new Object();
        Thread thread = new Thread(() -> {
            // 那么直接让当前线程进入到阻塞状态
            synchronized (obj) {
                try {
                    System.out.println("线程thread开始来进行执行.............");
                    obj.wait(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        // main线程开始来进行抢锁,执行完了释放锁
        synchronized (obj) {
            System.out.println("hello,world");
        }
    }
}

没有参数:

public class TestWaitTwo {

    public static void main(String[] args) {
        Object obj = new Object();
        Thread thread = new Thread(() -> {
            // 那么直接让当前线程进入到阻塞状态
            synchronized (obj) {
                try {
                    System.out.println("线程thread开始来进行执行.............");
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        // main线程开始来进行抢锁,执行完了释放锁
        synchronized (obj) {
            System.out.println("hello,world");
        }
    }
}

没有参数和有参数为0,在效果上是一样的。

有参数的数值来进行操作,也就是最开始的案例中的例子。在等待了n秒钟之后,再次尝试来获取得到锁,此时此刻依然是可以获取得到锁的。

posted @ 2022-03-25 23:52  写的代码很烂  阅读(92)  评论(0编辑  收藏  举报