java多執行緒之間的通訊
一、使用wait()和notify()方法結合實現通訊
注意:wait()和notify()必須在synchronized中使用
wait():是當前執行緒休眠並且釋放鎖。
notify():喚醒另一個執行緒
例項:input執行緒向共享資料中寫入一條資料,out執行緒重共享資料中讀一條資料。
/**
* 共享資源物件
* @author Administrator
*
*/
class Res{
private String name;
private String sex;
private boolean flag=false;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public String toString() {
return "Res [name=" + name + ", sex=" + sex + "]";
}
}
/**
* 生產者(寫入執行緒)
* @author Administrator
*
*/
class InputThread extends Thread{
Res res;
int count=0;
public InputThread(Res res) {
this.res=res;
}
@Override
public void run() {
while(true) {
synchronized (res) {
if(res.isFlag()) {
try {
//當前執行緒進入睡眠
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(count==0) {//偶數
res.setName("張三丰");
res.setSex("男");
}else {//奇數
res.setName("李冰冰");
res.setSex("女");
}
//算奇、偶數的
count=(count+1)%2;
//設定標識
res.setFlag(true);
//喚醒out執行緒
res.notify();
}
}
}
}
/**
* 消費者(輸出執行緒)
* @author Administrator
*
*/
class OutThread extends Thread{
Res res;
public OutThread(Res res) {
this.res=res;
}
@Override
public void run() {
while (true) {
synchronized (res) {
if(!res.isFlag()) {
try {
//當前執行緒進入睡眠
res.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(res);
res.setFlag(false);
//喚醒input執行緒
res.notify();
}
}
}
}
public class ThreadCommunication {
public static void main(String[] args) {
Res res=new Res();
InputThread input=new InputThread(res);
OutThread out=new OutThread(res);
input.start();
out.start();
}
}
輸出結果為:
Res [name=張三丰, sex=男]
Res [name=李冰冰, sex=女]
Res [name=張三丰, sex=男]
Res [name=李冰冰, sex=女]
Res [name=張三丰, sex=男]
Res [name=李冰冰, sex=女]
Res [name=張三丰, sex=男]
Res [name=李冰冰, sex=女]
Res [name=張三丰, sex=男]
二、使用LOCK鎖
使用lock鎖的格式為:
Lock lock=new ReentrantLock();
try {
//獲取鎖
lock.lock();
}catch (Exception e) {
}finally {
//釋放鎖
lock.unlock();
}
注意:使用lock必須try{}catch(){},釋放鎖放在finally裡面。
使用lock實現上面的例子
/**
* 共享資源物件
* @author Administrator
*
*/
class Res{
private String name;
private String sex;
private boolean flag=false;
private Lock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public Lock getLock() {
return lock;
}
public void setLock(Lock lock) {
this.lock = lock;
}
public Condition getCondition() {
return condition;
}
public void setCondition(Condition condition) {
this.condition = condition;
}
@Override
public String toString() {
return "Res [name=" + name + ", sex=" + sex + "]";
}
}
/**
* 生產者(寫入執行緒)
* @author Administrator
*
*/
class InputThread extends Thread{
Res res;
int count=0;
public InputThread(Res res) {
this.res=res;
}
@Override
public void run() {
while(true) {
try {
//獲取鎖
res.getLock().lock();
if(res.isFlag()) {
res.getCondition().await();
}
if(count==0) {
res.setName("張三丰");
res.setSex("男");
}else {
res.setName("李冰冰");
res.setSex("女");
}
count=(count+1)%2;
res.setFlag(true);
//喚醒對方相當於synchronized中用到的notify();
res.getCondition().signal();
}catch (Exception e) {
}finally {
//釋放鎖
res.getLock().unlock();
}
}
}
}
/**
* 消費者(輸出執行緒)
* @author Administrator
*
*/
class OutThread extends Thread{
Res res;
public OutThread(Res res) {
this.res=res;
}
@Override
public void run() {
while (true) {
try {
//獲取鎖
res.getLock().lock();;
if(!res.isFlag()) {
res.getCondition().await();
}
System.out.println(res);
res.setFlag(false);
res.getCondition().signal();
}catch (Exception e) {
}finally {
//釋放鎖
res.getLock().unlock();
}
}
}
}
public class ThreadLock {
public static void main(String[] args) {
Res res=new Res();
InputThread input=new InputThread(res);
OutThread out=new OutThread(res);
input.start();
out.start();
}
}