wait()、notify()、notifyAll()是三個定義在Object類裏的方法,可以用來控制線程的狀態。
這三個方法最終調用的都是jvm級的native方法。隨着jvm運行平臺的不同可能有些許差異。
- 如果對象調用了wait方法就會使持有該對象的線程把該對象的控制權交出去,然後處於等待狀態。
- 如果對象調用了notify方法就會通知某個正在等待這個對象的控制權的線程可以繼續運行。
- 如果對象調用了notifyAll方法就會通知所有等待這個對象控制權的線程繼續運行。
其中wait方法有三個over load方法:
wait()
wait(long)
wait(long,int)
wait方法通過參數可以指定等待的時長。如果沒有指定參數,默認一直等待直到被通知。
和synchronize結合使用
http://longdick.iteye.com/blog/453615 講解的異常java.lang.IllegalMonitorStateException。
- 任何一個時刻,對象的控制權(monitor)只能被一個線程擁有。
- 無論是執行對象的wait、notify還是notifyAll方法,必須保證當前運行的線程取得了該對象的控制權(monitor)
- 如果在沒有控制權的線程裏執行對象的以上三種方法,就會報java.lang.IllegalMonitorStateException異常。
- JVM基於多線程,默認情況下不能保證運行時線程的時序性
package com.swntek.czm.myzxingdemo;
public class NotifyTest {
private Boolean flag = true;
private Object obj = new Object();
class NotifyThread extends Thread {
public NotifyThread(String name) {
super(name);
}
public void run() {
try {
sleep(3000);//推遲3秒鐘通知
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj) {
flag = false;
obj.notifyAll();
}
}
}
class WaitThread extends Thread {
public WaitThread(String name) {
super(name);
}
public void run() {
synchronized (obj) {
while (flag) {
System.out.println(getName() + " begin waiting!");
long waitTime = System.currentTimeMillis();
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
waitTime = System.currentTimeMillis() - waitTime;
System.out.println("wait time :" + waitTime);
}
System.out.println(getName() + " end waiting!");
}
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("Main Thread Run!");
NotifyTest test = new NotifyTest();
NotifyThread notifyThread = test.new NotifyThread("notify01");
WaitThread waitThread01 = test.new WaitThread("waiter01");
WaitThread waitThread02 = test.new WaitThread("waiter02");
WaitThread waitThread03 = test.new WaitThread("waiter03");
notifyThread.start();
waitThread01.start();
waitThread02.start();
waitThread03.start();
}
}
jdk1.5Lock取代了synchronized
Condition替代了wait notify
newCondition() |
private Lock lock=new ReentrantLock();
private Lock lock=new ReentrantLock();
Condition con=lock.newCondition();
con.await();con.signal();con.signalAll()
http://ifeve.com/understand-condition/
package com.swntek.czm.myzxingdemo;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class NotifyTest {
private static Lock reentrantLock = new ReentrantLock();
private static Condition condition;
private Boolean flag = true;
class NotifyThread extends Thread {
public NotifyThread(String name) {
super(name);
}
public void run() {
try {
sleep(3000);//推遲3秒鐘通知
} catch (InterruptedException e) {
e.printStackTrace();
}
reentrantLock.lock();
flag = false;
condition.signalAll();
reentrantLock.unlock();
}
}
class WaitThread extends Thread {
public WaitThread(String name) {
super(name);
}
public void run() {
reentrantLock.lock();
while (flag) {
System.out.println(getName() + " begin waiting!");
long waitTime = System.currentTimeMillis();
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
waitTime = System.currentTimeMillis() - waitTime;
System.out.println("wait time :" + waitTime);
}
System.out.println(getName() + " end waiting!");
reentrantLock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("Main Thread Run!");
condition = reentrantLock.newCondition();
NotifyTest test = new NotifyTest();
NotifyThread notifyThread = test.new NotifyThread("notify01");
WaitThread waitThread01 = test.new WaitThread("waiter01");
WaitThread waitThread02 = test.new WaitThread("waiter02");
WaitThread waitThread03 = test.new WaitThread("waiter03");
notifyThread.start();
waitThread01.start();
waitThread02.start();
waitThread03.start();
}
}