線程間通訊:
多個(gè)線程在處理同一資源,但是任務(wù)卻不同 。

比如對于同一個(gè)資源,一邊在輸入,一邊在輸出:
class Resource{
String name;
String sex;
}
//輸入
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r=r;
}
public void run(){
int x=0;
while(true){
synchronized(r){//因?yàn)镽esource是共同操作的,所以r可以作為鎖
if(x==0){
r.name="mike";
r.sex="nan";
}else{
r.name="麗麗";
r.sex="女女女女";
}
x=(x+1)%2;
}
}
}
}
//輸出
class Output implements Runnable{
Resource r;
Output(Resource r){
this.r=r;
}
public void run(){
while(true){
synchronized(r){
System.out.print(r.name+"..."+r.sex);
}
}
}
}
public class TongXun {
public static void main(String[] args) {
//創(chuàng)建資源
Resource r=new Resource();
//創(chuàng)建任務(wù)
Input in=new Input(r);
Output out=new Output(r);
//創(chuàng)建線程,執(zhí)行路徑
Thread t1=new Thread(in);
Thread t2=new Thread(out);
//開啟線程
t1.start();
t2.start();
}
}
運(yùn)行:
等待喚醒機(jī)制:
涉及的方法:
1 wait():讓線程處于凍結(jié)狀態(tài),被wait的線程會被存儲到線程池當(dāng)中。
2 notify():喚醒線程池中的任意一個(gè)線程。
3 notifyAll():喚醒線程池中的所有線程
這些方法都必須定義在同步中。
因?yàn)檫@些方法是用于操作線程狀態(tài)的方法。
必須要明確到底操作得是哪個(gè)鎖上的線程。
class Resource{
String name;
String sex;
boolean flag=false;
}
//輸入
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r=r;
}
public void run(){
int x=0;
while(true){
synchronized(r){//因?yàn)镽esource是共同操作的,所以r可以作為鎖
if(r.flag)
try{
r.wait();
}catch(InterruptedException e){
}
if(x==0){
r.name="mike";
r.sex="nan";
}else{
r.name="麗麗";
r.sex="女女女女";
}
r.flag=true;
r.notify();
}
x=(x+1)%2;
}
}
}
//輸出
class Output implements Runnable{
Resource r;
Output(Resource r){
this.r=r;
}
public void run(){
while(true){
synchronized(r){
if(!r.flag)
try{
r.wait();
}catch(InterruptedException e){
}
System.out.println(r.name+"..."+r.sex);
r.flag=false;
r.notify();
}
}
}
}
public class NofityDemo {
public static void main(String[] args) {
//創(chuàng)建資源
Resource r=new Resource();
//創(chuàng)建任務(wù)
Input in=new Input(r);
Output out=new Output(r);
//創(chuàng)建線程,執(zhí)行路徑
Thread t1=new Thread(in);
Thread t2=new Thread(out);
//開啟線程
t1.start();
t2.start();
}
}
運(yùn)行:
等待喚醒機(jī)制避免了成片的輸出的現(xiàn)象,因?yàn)榈却龁拘褭C(jī)制做的就是當(dāng)一個(gè)資源被輸入,資源被占有,只有先輸出了才能再次輸入資源
思考1:wait(),notify(),notifyAll(),用來操作線程為什么定義在了Object類中?
1 這些方法存在于同步中;
2 使用這些方法時(shí)必須要標(biāo)識所屬的同步的鎖。
3 鎖可以是任意對象,所以任意對象調(diào)用的方法一定定義在Object類中。
優(yōu)化:
資源一般都是私有的,這里資源進(jìn)行私有化,并對外提供方法。
class Resource{
private String name;
private String sex;
private boolean flag=false;
public synchronized void set(String name,String sex){
if(flag)
try{
this.wait();
}catch(InterruptedException e){
}
this.name=name;
this.sex=sex;
flag=true;
this.notify();
}
public synchronized void Out(){
if(!flag)
try{
this.wait();
}catch(InterruptedException e){
}
System.out.println(name+"...優(yōu)化..."+sex);
flag=true;
this.notify();
}
}
//輸入
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r=r;
}
public void run(){
int x=0;
while(true){
if(x==0){
r.set("mike","nan");
}else{
r.set("mike","nan");
}
x=(x+1)%2;
}
}
}
//輸出
class Output implements Runnable{
Resource r;
Output(Resource r){
this.r=r;
}
public void run(){
while(true){
r.Out();
}
}
}
public class NofityDemo {
public static void main(String[] args) {
//創(chuàng)建資源
Resource r=new Resource();
//創(chuàng)建任務(wù)
Input in=new Input(r);
Output out=new Output(r);
//創(chuàng)建線程,執(zhí)行路徑
Thread t1=new Thread(in);
Thread t2=new Thread(out);
//開啟線程
t1.start();
t2.start();
}
}
運(yùn)行:
思考2:wait(),sleep()有什么區(qū)別?
wait()釋放執(zhí)行權(quán),釋放鎖;sleep()釋放cpu執(zhí)行權(quán),不釋放鎖。