sleep, yield, wait的区别

1.sleep(long millis)

Thread的静态方法,使当前线程(即调用Thread.sleep(long millis)的线程)暂停执行一段时间(暂时让出CPU),让其他线程(任何优先级)有机会继续执行,但它并不释放对象锁。当睡眠到指定的时间后,时间事件触发,当前线程继续执行。源代码如下:


方法需要抛出InterruptedException异常。

如果sleep方法包裹在synchronized内,如:

synchronized (this) {

//其他代码省略
try{
Thread.sleep(10000);
}catch(InterruptedException e){

//省略
return;  
}
}

假设有线程A,B将会执行如下代码,则当A线程执行该代码,进入睡眠后,线程B获得CPU执行权限,线程B执行其他非同步动作,当线程B需要执行该同步代码块时,由于线程A持有该共享代码块的锁(睡眠时没有释放),则线程B被挂起,等待线程A释放该对象锁。

理论上,线程被挂起后(Blocked),不重新参与CPU的竞争,所以低优先级的线程都有机会获取CPU执行权限。

2. yield

Thread类的静态方法。使当前线程(即调用Thread.yield()的线程)暂时让出CPU,让高优先级的线程获取CPU的执行权限。当前线程由RUNNING状态变成RUNABLE状态,重新竞争CPU时间。如果没有更高优先级的线程,则当前线程继续获取CPU的执行权限。yield也不会释放线程持有的对象锁。源代码如下:


3. join

Thread对象的实例方法。将并行执行强行变成串行执行。源代码如下:


比如有主线程,以及线程t,当执行t.join()后,必须要等线程t执行完成,主线程才能继续执行。即打印语句肯定是等待线程t执行后才能执行。


3. wait, notify, notifyAll

这三个方法用于协调多个线程对共享数据的存取,所以必须在synchronized语句块内使用。synchronized关键字用于保护共享数据,阻止其他线程对共享数据的存取,但是这样程序的流程就很不灵活了,如何才能在当前线程还没退出synchronized数据块时让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。

wait()方法使当前线程暂停执行并释放对象锁标示,让其他线程可以进入synchronized数据块,当前线程被放入对象等待池中。当调用notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。

notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。

注意 这三个方法都是Java.lang.Object的方法。


final Object synObj = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(synObj) {
System.out.println("T1获取synObj的对象监视器,开始执行同步块");
try {
Thread.sleep(10000);//休眠,不会释放对象锁
synObj.wait();//t1此刻被挂起,释放对象锁
System.out.println("T1被T2唤醒后并重新获得synObj的对象监视器,继续执行");
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1获取synObj的对象监视器,结束同步块");
} };
});
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("T2启动,但是因为T1占用了synObj的对象监视器,则等待T1执行synObj.wait来释放它");
synchronized(synObj) {
try {
System.out.println("在T1执行synObj.wait后,T2获取synObj的对象监视器,进入同步块");
synObj.notify();
System.out.println("T2执行synObj.notify(),T1被唤醒,但T2还在同步块中,没有释放synObj的对象监视器,T1等待synObj的对象监视器");
TimeUnit.MINUTES.sleep(1);
System.out.println("T2结束同步块,释放synObj的对象监视器,T1获取到synObj的对象监视器,并执行wait后面的操作");
}catch(InterruptedException e) {
e.printStackTrace();
}
} };
});
t2.start();

源代码如下:


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值