多線程進階之等待喚醒機制
阿新 • • 發佈:2018-11-16
err read spa zed bject vat stat 算法 pre
/* * 線程間通訊實例 * 多個線程在處理同一資源,但是任務不同 */ //資源 class Resource { String name; String sex; } //輸入 class Input implements Runnable { Resource r;//類對象 public Input(Resource r)//類對象做構造參數-->初始化資源 { this.r=r; } public void run() { int x=0; while(true) {/* * 加上同步鎖,因為輸入輸出任務共享資源,所以將資源對象r作為鎖 * 也是為了讓輸入輸出處於同一同步鎖中,這樣輸入就不會在輸入姓名林玲還沒有賦值完性別女 * 時(周俊明被林玲覆蓋),切換執行權 */ synchronized(r) { if(x==0) { r.name="周俊明"; r.sex="男"; }else { r.name="林玲"; r.sex="女"; } } x=(x+1)%2;//算法切換:不斷由if和else切換 } } } //輸出 class Output implements Runnable { Resource r; public Output(Resource r) { this.r=r; }public void run() { while(true) { synchronized(r) { System.out.println(r.name+"....."+r.sex); } } } } public class ResourceDemo { public static void main(String[] args) { //創建資源 Resource r=new Resource(); //創建任務 Input in=new Input(r); Output out=new Output(r); //創建線程 Thread t1=new Thread(in); Thread t2=new Thread(out); t1.start(); t2.start(); } }
變身 :
/** * 等待/喚醒機制 * * 涉及的方法: * * 1.wait():讓線程處於凍結狀態,被wait的線程會被存儲到線程池中. * 2.notify():喚醒線程池中的一個線程(任意) * 3.notifyAll():喚醒線程池中的索引線程. * * 這些方法都必須定義在同步中 * 因為這些方法是用於操作線程狀態的方法 * 必須要明確到底操作的是哪個鎖上的線程 * * 為什麽操作線程的方法wait notify notifyAll定義在Object類中 * * 因為這些方法是監視器的方法.監視器就是鎖 * 鎖可以是任意的對象,任意的對象調用的方式一定定義在object類中 * */ //資源 class Resour { String name; String sex; boolean flag=false;//標記 } //輸入 class Inputs implements Runnable { Resour r;//類對象 public Inputs(Resour r)//類對象做構造參數-->初始化資源 { this.r=r; } public void run() { int x=0; while(true) { /* * 加上同步鎖,因為輸入輸出任務共享資源,所以將資源對象r作為鎖 * 也是為了讓輸入輸出處於同一同步鎖中,這樣輸入就不會在輸入姓名林玲還沒有賦值完性別女 * 時(周俊明被林玲覆蓋),切換執行權 */ synchronized(r) { try { if(r.flag) r.wait(); //標明睡眠/喚醒同一鎖上線程 } catch (InterruptedException e) { // TODO: handle exception } if(x==0) { r.name="周俊明"; r.sex="男"; } else { r.name="林玲"; r.sex="女"; } r.flag=true; r.notify(); } x=(x+1)%2;//算法切換:不斷由if和else切換 } } } //輸出 class Outputs implements Runnable { Resour r; public Outputs(Resour r) { this.r=r; } public void run() { while(true) { synchronized(r) { try { if(!r.flag) r.wait(); } catch (InterruptedException e) { } System.out.println(r.name+"....."+r.sex); r.flag=false; r.notify(); } } } } public class ResourceDemo1 { public static void main(String[] args) { //創建資源 Resour r=new Resour(); //創建任務 Inputs in=new Inputs(r); Outputs out=new Outputs(r); //創建線程 Thread t1=new Thread(in); Thread t2=new Thread(out); t1.start(); t2.start(); } }
優化:
//資源 class Resours { 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+"..."+sex); flag=false; this.notify(); } } //輸入 class Inputce implements Runnable { Resours r;//類對象 public Inputce(Resours r)//類對象做構造參數-->初始化資源 { this.r=r; } public void run() { int x=0; while(true) { /* * 加上同步鎖,因為輸入輸出任務共享資源,所以將資源對象r作為鎖 * 也是為了讓輸入輸出處於同一同步鎖中,這樣輸入就不會在輸入姓名林玲還沒有賦值完性別女 * 時(周俊明被林玲覆蓋),切換執行權 */ if(x==0) { r.set("周俊明","男"); } else { r.set("林玲","女"); } x=(x+1)%2;//算法切換:不斷由if和else切換 } } } //輸出 class Outputce implements Runnable { Resours r; public Outputce(Resours r) { this.r=r; } public void run() { while(true) { r.out(); } } } public class ResourceDemo2 { public static void main(String[] args) { //創建資源 Resours r=new Resours(); //創建任務 Inputce in=new Inputce(r); Outputce out=new Outputce(r); //創建線程 Thread t1=new Thread(in); Thread t2=new Thread(out); t1.start(); t2.start(); } }
一不小心就暴露了真實姓名
多線程進階之等待喚醒機制