1. 9IM首页
  2. 热点

浅析wait(),join(),sleep()方法

首先需要对wait(),join(),sleep()方法进行介绍。

Object.wait()方法是什么?

调用wait()方法前线程必须持有对象Object的锁。线程调用wait()方法后,会释放当前的Object锁,进入锁的monitor对象的等待队列,直到有其他线程调用notify()/notifyAll()方法唤醒等待锁的线程。

需要注意的是,其他线程调用notify()方法只会唤醒单个等待锁的线程,如果有多个线程都在等待这个锁的话,不一定会唤醒到之前调用wait()方法的线程。

同样,调用notifyAll()方法唤醒所有等待锁的线程之后,也不一定会马上把时间片分给刚才放弃锁的那个线程,具体要看系统的调度。

Thread.join()方法是什么?

join()方法是Thread类的一个实例方法。它的作用是让当前线程陷入“等待”状态,等join的这个线程threadA执行完成后,再继续执行当前线程。

实现原理是join()方法本身是一个sychronized修饰的方法,也就是调用join()这个方法需要先获取threadA的锁,获得锁之后再调用wait()方法来进行等待,一直到threadA执行完成后,threadA会调用notify_all()方法,唤醒所有等待的线程,当前线程才会结束等待。

Thread threadA = new Thread();
threadA.join();

join()方法的源码:

public final void join() throws InterruptedException {
    join(0);//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;
        }
    }
}

这是jvm中Thead的源码,在线程执行结束后会调用notify_all来唤醒等待的线程。

//一个c++函数:
void JavaThread::exit(bool destroy_vm, ExitType exit_type) ;
//里面有一个贼不起眼的一行代码
ensure_join(this);

static void ensure_join(JavaThread* thread) {
  Handle threadObj(thread, thread->threadObj());

  ObjectLocker lock(threadObj, thread);

  thread->clear_pending_exception();

  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);

  java_lang_Thread::set_thread(threadObj(), NULL);

  //同志们看到了没,别的不用看,就看这一句
  //thread就是当前线程,是啥?就是刚才例子中说的threadA线程
  lock.notify_all(thread);

  thread->clear_pending_exception();
}

sleep()方法是什么?

sleep方法是Thread类的一个静态方法。它的作用是让当前线程睡眠一段时间。:sleep方法是不会释放当前的锁的,而wait方法会。

sleep与wait方法的区别:

  • wait可以指定时间,也可以不指定;而sleep必须指定时间。
  • wait释放cpu资源,同时释放锁;sleep释放cpu资源,但是不释放锁,所以易死锁。(调用join()方法也不会释放锁)
  • wait必须放在同步块或同步方法中,而sleep可以再任意位置。

原创文章,作者:9IM,如若转载,请注明出处:https://www.9im.cn/738.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注