wait、sleep、interrupt、notify

来源:互联网 发布:java一般怎么调试文件 编辑:程序博客网 时间:2024/05/17 21:57

Wait

导致当前的线程等待,直到其他线程调用此对象的 notify方法或 notifyAll 方法。

当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。

Sleep

在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。该线程不丢失任何监视器的所属权。

Wait与Sleep。。。

Wait是Object类的方法,范围是使该Object实例所处的线程。

Sleep()是Thread类专属的静态方法,针对一个特定的线程。

一般情况下在线程中若只是想暂停就可以不用wait,只要用Thread.sleep(...)这个方法,就像睡觉会睡过点一样,sleep的线程在时间结束后也不一定能够立即恢复执行。

//线程A中
try...{
System.out.println("A will sleep");
this.sleep();
}catch(InterruptedException e)...{
//A已经被中断了
System.out.println("A was interrupted");
}

//其他线程中
A.interrupt();
如果使用Wait方法需要通过Lock进行互斥,不然会抛出java.lang.IllegalMonitorStateException异常。

private Object lock = new Object();
...
synchronized (getLock()) ......{
getLock().wait(timeout);
}
...
protected Object getLock() ......{
return lock;
}
...
public void broadcast() ...{
synchronized (getLock()) ...{
getLock().notifyAll();
}
}
上述实现了在一个Thread中使用wait等待的方法,由一个Fine-grain 锁来控制线程的互斥。

Wait方法使实体所处线程暂停执行,从而使对象进入等待状态,直到被notify方法通知或者wait的等待的时间到。Sleep方法使持有的线程暂停运行,从而使线程进入休眠状态,直到用interrupt方法来打断他的休眠或者sleep的休眠的时间到。

Wait方法进入等待状态时会释放同步锁(如上例中的lock对象),而Sleep方法不会释放同步锁。所以,当一个线程无限Sleep时又没有任何人去interrupt它的时候,程序就产生大麻烦了。

亲密。。。与notify。。。与interrupt。。。

wait与notify。。。

notify是用来通知线程,但在notify之前线程是需要获得lock的。另个意思就是必须写在synchronized(lockobj) {...}之中。wait也是这个样子,一个线程需要释放某个lock,也是在其获得lock情况下才能够释放,所以wait也需要放在synchronized(lockobj) {...}之中。看下下面的例子:

//在线程A中
synchronized(lockobject) ...{
  while(!condition) ...{
    lockobject.wait();
  }
  //TODO 该运行的部分
}
  
//在线程B中
synchronized(lockobject) ...{
  condition = true;
  lockobject.notify();
}

A线程获得lock之后不断的判断条件,不满足的时候就释放lock,进入等待。B获得lock,并且改变条件,之后通知A,之后B离开lock区,A获得lock执行该运行的部分。

Sleep与notify。。。

我感觉他们凑在一起没有任何的意义,因为线程在Sleep时并不会释放他占有的lock,所以notify并不能唤醒他。

Sleep与interrupt。。。

interrupt是个很暴力的方法,打断一个线程的Sleep时并不需要获得该线程的lock。虽然暴力却也有暴力的用处。在一个线程无时限sleep的时候也只有interrupt能够唤醒他。在interrupt的时候会抛出InterruptedException,这个Exception是由Thread 类自动抛出的。因此Interrupt带有强烈的阻塞味道。

wait与interrupt。。。

interrupt同样可以打断wait的等待,与打断sleep不同的是,被打断的wait的线程在重新获得lock之前是不会抛出InterruptedException。

遗忘。。。resume与suspend。。。

resume和suspend已经被Java遗弃,因为他们天生会引起线程的死锁。

suspend是个贪婪的家伙,当一个线程在suspend的时候,线程会停下来,但却仍然持有在这之前获得的锁定。其他线程无法使用他锁定的任何资源,除非这个挂起的线程被resume之后,他才会继续运行。对于线程的同步,使用wait与notify要安全的多。

原创粉丝点击