繼續來看blog:http://blog.csdn.net/zyplus/article/details/6672775 java
「Obj.wait(),與Obj.notify()必需要與synchronized(Obj)一塊兒使用,也就是wait,與notify是針對已經獲取了Obj鎖進行操做,從語法角度來講就是Obj.wait(),Obj.notify必須在synchronized(Obj){...}語句塊內。從功能上來講wait就是說線程在獲取對象鎖後,主動釋放對象鎖,同時本線程休眠。直到有其它線程調用對象的notify()喚醒該線程,才能繼續獲取對象鎖,並繼續執行。相應的notify()就是對對象鎖的喚醒操做。但有一點須要注意的是notify()調用後,並非立刻就釋放對象鎖的,而是在相應的synchronized(){}語句塊執行結束,自動釋放鎖後,JVM會在wait()對象鎖的線程中隨機選取一線程,賦予其對象鎖,喚醒線程,繼續執行。這樣就提供了在線程間同步、喚醒的操做。Thread.sleep()與Object.wait()兩者均可以暫停當前線程,釋放CPU控制權,主要的區別在於Object.wait()在釋放CPU同時,釋放了對象鎖的控制。」 ide
咱們來寫段測試數據:一個線程往MAP寫數據,另一個線程讀數據。 測試
package com.jdcloud.xue.gang.data.put.get; this
import java.util.HashMap; atom
import java.util.Map; spa
import java.util.concurrent.ExecutorService; .net
import java.util.concurrent.Executors; 線程
import java.util.concurrent.atomic.AtomicInteger; 調試
public class DataPuterAndGetter { 對象
//用戶放置數據的MAP
public static final Map<String, String> StrMap = new HashMap<String, String>();
//用於自增
public static final AtomicInteger atomicInteger = new AtomicInteger(0);
//鎖
public static final Object LOCKER = new Object();
/**
* 一個線程來讀取MAP中的數據
* */
static class DataGetter extends Thread {
private Object locker;
public DataGetter(Object locker) {
this.locker = locker;
}
@Override
public void run() {
while (true) {
synchronized (locker) {
if (StrMap.size() > 0) {
System.out.println(StrMap);
StrMap.clear();
try {
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
/**
* 一個線程來把數據放置到MAP中
* */
static class DataPutter extends Thread {
private AtomicInteger atomicInteger;
private Object locker;
public DataPutter(Object locker,AtomicInteger atomicInteger) {
this.locker = locker;
this.atomicInteger = atomicInteger;
}
public void run() {
while (true) {
synchronized (locker) {
int num = atomicInteger.addAndGet(1);
System.out.println("index is : ---->" + num);
StrMap.put("NUM_"+num, "index is :" + num);
locker.notify();
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 測試方法
* */
public static void main(String args[]){
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new DataPuterAndGetter.DataPutter(DataPuterAndGetter.LOCKER,DataPuterAndGetter.atomicInteger) );
executorService.execute(new DataPuterAndGetter.DataGetter(DataPuterAndGetter.LOCKER));
executorService.execute(new DataPuterAndGetter.DataGetter(DataPuterAndGetter.LOCKER));
}
}
以上程序用LOCKER來協調讀寫,可是synchronized 同一個LOCKER對應的內存塊,並無實現塞一個數據到MAP中,立刻從MAP中讀取一條數據出來。有點像MQ的味道了。
Blog提到了順序打印ABC,調試後能夠發現程序中處於wait狀態的線程,仍是須要修改下,也就是當程序結束時,調用LOCKER的notify方法。
整個測試程序以下:
package com.jdcloud.xue.gang.print;
public class Muti3Printer extends Thread {
private Object pre_LOCKER = new Object();
private Object self_LOCKER = new Object();
private Object next_LOCKER = new Object();
private String name;
public Muti3Printer(Object pre_LOCKER, Object self_LOCKER,
Object next_LOCKER, String name) {
super();
this.pre_LOCKER = pre_LOCKER;
this.self_LOCKER = self_LOCKER;
this.next_LOCKER = next_LOCKER;
this.name = name;
}
@Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (pre_LOCKER) {
synchronized (self_LOCKER) {
System.out.print(name);
count--;
self_LOCKER.notify();
}
try {
pre_LOCKER.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//程序結束後,解除全部的鎖
synchronized (pre_LOCKER){
pre_LOCKER.notify();
}
synchronized (self_LOCKER){
self_LOCKER.notify();
}
synchronized (next_LOCKER){
next_LOCKER.notify();
}
System.out.print("\n out -->" + name);
}
public static void main(String args[]) throws InterruptedException {
Object A_LOCKER = new Object();
Object B_LOCKER = new Object();
Object C_LOCKER = new Object();
Muti3Printer a_printer = new Muti3Printer(C_LOCKER, A_LOCKER, B_LOCKER,
"A");
Muti3Printer b_printer = new Muti3Printer(A_LOCKER, B_LOCKER, C_LOCKER,
"B");
Muti3Printer c_printer = new Muti3Printer(B_LOCKER, C_LOCKER, A_LOCKER,
"C");
a_printer.start();
Thread.sleep(100L);
b_printer.start();
Thread.sleep(100L);
c_printer.start();
}
}