join和sleep的区别

sleep是Thread的静态方法,作用是使当前线程“睡眠”一定时间,期间线程不会释放对象锁。

  public static native void sleep(long millis) throws InterruptedException;

join是Thread的普通方法,作用是等待调用join方法的线程死亡,才能接着执行当前线程的后续方法。例如,常用于主线程需要等待子线程结束后,才能执行主线程中join方法之后的代码的场景。

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

join和sleep从使用效果上来看,都能使线程处于“阻塞”状态,两者的主要区别是,sleep睡眠期间不会释放对象锁,像一个占有欲很强的小孩,睡觉了还死死地抱着布偶娃娃。join因为内部实现使用了wait方法,当前线程所持有的锁会被释放。从源码分析,

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);              --------wait()会释放对象锁
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);          --------wait()会释放对象锁
                now = System.currentTimeMillis() - base;
            }
        }
    }

理论是枯燥的,举个对比的例子:

public class TestJoinAndSleep {
    static class Service extends Thread {
        public synchronized void method() {
            System.out.println("method " + ", time = " + System.currentTimeMillis());
        }

        @Override
        public void run() {
            System.out.println("run begin" + ", time = " + System.currentTimeMillis());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("run end" + ", time = " + System.currentTimeMillis());
        }
    }

    static class ThreadA extends Thread {
        Service service;
        ThreadA(Service service) {
            super();
            this.service = service;
        }

        @Override
        public void run() {
            try {
                synchronized (service) {
                    service.start();
                    Thread.sleep(6000);    //注意这里
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    static class ThreadB extends Thread {
        Service service;
        ThreadB(Service service) {
            super();
            this.service = service;
        }

        @Override
        public void run() {
            service.method();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();

        Thread.sleep(1000);

        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
    }

执行后的结果如下:ThreadA在run方法中持有Service对象的锁,在sleep(6000)后释放对象锁,因为ThreadB要在6秒后才能拿到Service的那一把锁,才能执行method方法

run begin, time = 1596982444974
run end, time = 1596982449978
method , time = 1596982450981  //和run begin差6秒

将ThreadA run方法中的sleep替换为join,输出如下,method和run begin相差1s,在ThreadA的run方法join执行后,释放锁,b线程抢到了锁,执行method方法。

    public void run() {
            try {
                synchronized (service) {
                    service.start();
                    //Thread.sleep(6000);
                    service.join();
                    for (int i = 0; i < Integer.MAX_VALUE; i++) {
                        String str = new String();
                        Math.random();
                    }
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
run begin, time = 1596982735081
method , time = 1596982736098
run end, time = 1596982740091

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值