黑馬程序員_Java基礎[29]_線程間通訊、解決問題、lock

---------- android培訓 java培訓 、期待與您交流! ----------


/*
 * 線程間通訊:-解決安全問題
 * 其實就是多個線程在操作同一個資源
 * 但是操作的動作不同

 */
/*【用舉例的思路註解】
 * 【1】編寫完畢,
 * 【2】運行我們發現,小煥煥的性別一會女一會man, 是線程出現了安全漏洞
 * 接下來,我們封堵上這個漏洞。採用同步
 *                        想到2個前提,
 * 同步的前提
 * 1、必須有2個以上的線程  【a】【b】
 * 2、必須是一個鎖
 *         我們先用的是obj 發現不是同一個,然後用了this 也不是,那麼該程序在內存總有一個是唯一的
 *             發現,內存裏有4個類,類名.class   然後我們繼續看,這個程序裏,還有一個對象是唯一的
 *             那就是主函數中的【r】。

 * 【3】搞定以後,我們發現,按道理應該是存一個打印一個纔對。
 * 【等待喚醒機制】  wait();等待    notify();喚醒    notifyAll();全部喚醒  都必須有監視器,就是鎖
 *
 * 這三個方法,都使用在同步中,因爲要持有監視器(鎖)的線程操作,
 * 所以要使用在同步中,因爲只有同步才具有監視器(鎖)的感念
 *
 * 爲什麼這些操作線程的方法要定義在Object類中呢?
 * 因爲這些 方法在操作同步中線程時,都必須要表示他們所操作線程持有的鎖
 * 只有同一個鎖上的被等待線程,可以被同一個鎖上的notify喚醒
 * 不可以對不同鎖中的線程進行喚醒

 *
 * 也就是說:等待和喚醒必須是同一個鎖
 *
 * 而鎖可以是任意對象,所以可以被任意對象調用的方法定義在Object中
 */

//設計一個煤礦堆
class Res{
    String name;
    String set;
    boolean falg = false;
}
//設計一個進貨的貨車
class Input implements Runnable{
    private Res r;
    Input(Res r){
        this.r=r;
    }
    Object obj=new Object();
    public void run(){
        int x=0;

        while(true){
            synchronized(r){//【a】    
                
                    if(r.falg)
                            try{r.wait();}

                           catch(Exception e){}
                    if(x==0){    
                        r.name="Yunyao";
                        r.set="man";
                    }
                    else{
                        r.name="小煥煥";
                        r.set="女";
                    }
                    x=(x+1)%2;    
                    r.falg=true;
                    r.notify();
            }
        }
    }    
}
//設計一個拉貨的貨車
class Output implements Runnable{
    private Res r;
    Output(Res r){
        this.r=r;
    }
    Object obj=new Object();
    public void run(){
        //int x=0;
        while(true){
            synchronized(r){//【b】
                if(!r.falg)
                    try{r.wait();}catch(Exception e){}
                System.out.println(r.name+"..."+r.set+"...");
                //x+=1;
                r.falg=false;
                r.notify();
            
            }
        }            
    }
}
public class D_Th_InputOutpt {
    public static void main(String[] args) {
        Res r=new Res();//創建一個煤礦堆  程序中唯一的一個對象。
        
        Input  in = new Input(r); //創建一個進貨的車
        Output ot = new Output(r);//創建一個出貨的車
        
        Thread t1 = new Thread(in);//進入高速通道
        Thread t2 = new Thread(ot);
        
        t1.start();// 開始跑起走
        t2.start();

    }
}

--------------------------------------------------------------------------------------------------------

優化一

package _Day12;
/*
 * 對前一個問題進行優化。
 */

//設計一個煤礦堆
class Res1{
    private String name;
    private String set;
    boolean falg = false;
    //同步函數   非靜態同步函數 用的鎖是  this ,記住了。
    public synchronized void setInfo(String name,String set){
        if(falg)
            try{this.wait();}catch(Exception e){}
        this.name=name;
        this.set=set;
        this.falg=true;
        this.notify();
    }
    public synchronized void showInfo(){
        if(!falg)
            try{this.wait();}catch(Exception e){}
        System.out.println(this.name+"..."+this.set);
        this.falg=false;
        this.notify();
    }
}
//設計一個進貨的貨車
class Input1 implements Runnable{
    private Res1 r;
    Input1(Res1 r){
        this.r=r;
    }
    public void run(){
        int x=0;
        while(true){                
            if(x==0)    
                r.setInfo("fei", "man");
            else
                r.setInfo("小煥煥", "女女女女女");
            x=(x+1)%2;    
        }
    }    
}
//設計一個拉貨的貨車
class Output1 implements Runnable{
    private Res1 r;
    Output1(Res1 r){
        this.r=r;
    }
    public void run(){
        while(true){
            r.showInfo();
        }            
    }
}




public class D_Th_YouhuaInOut {
    public static void main(String[] args) {
        Res1 r=new Res1();//創建一個煤礦堆
        
        new Thread(new Input1(r)).start();
        new Thread(new Output1(r)).start();
        /* 六句優化成上面兩句【 匿名對象形式】
        Input1  in = new Input1(r); //創建一個進貨的車
        Output1 ot = new Output1(r);//創建一個出貨的車
        
        Thread t1 = new Thread(in);//進入高速通道
        Thread t2 = new Thread(ot);
        
        t1.start();// 開始跑起走
        t2.start();
        */
    }

}

---------------------------------------------------------------------------------------------
/*
 * 線程間通信--生產者消費者
 */


        /*當生產和消費是單線程的時候沒有問題,下面我們把兩條線都加一倍試試
           發現有問題,經判斷是因爲線程被喚醒後沒有對falg再次進行判斷
                因爲if只執行一次,現在,我們把if替換成while試試
                發現4個線程出現了同時等待。。。。
            notify喚醒的是線程池中第一個被等待的線程,很有可能就是本方的,
                導致所有線程等待,從而數據錯亂
            而使用while 則容易出現線程全部出現同時等待的現象。
            
            所以必須使用:notifyAll  全部喚醒
                因爲有while,所以都會循環去判斷標記,進入循環漸進的生成消費。
                
            【自我總結】【注意:1.5以前版本使用】升級1.5里程碑版本的時候改
                成了5.0具體【【【LOCK】】】優化synchronized 請看D_Th_Lock
                當有多條線程時候,必須要使用while,notifyAll
                    while 必須去判斷標記,是不是在標記允許範圍內做動作
                    notifyAll 要把對方喚醒,
        
        */
        public class D_Th_YouhuaInOut2 {
        public static void main(String []args){
               Resource r=new Resource();
               new Thread(new Shengc(r)).start();
               new Thread(new Shengc(r)).start();
               new Thread(new Xiaof(r)).start();
               new Thread(new Xiaof(r)).start();

        
        Shengc sc=new Shengc(r);
               Xiaof  xf=new Xiaof(r);
        /*
        Thread t1=new Thread(sc);
        Thread t2=new Thread(xf);
        Thread t3=new Thread(sc);
        Thread t4=new Thread(xf);
        t1.start();
        t2.start();
        t3.start();
        t4.start();

        */
    }
}

class Resource{
    private String name;
    private int count=1;
    private boolean falg=false;
    public synchronized void set(String name){
        while(falg)
            try{this.wait();}catch(Exception e){}
        this.name=name+"..."+count++;
        
        System.out.println(Thread.currentThread().getName()+"..生產.."+this.name);
        this.falg=true;
        this.notifyAll();    
    }
    public synchronized void get(){
        while(!falg)
            try{this.wait();}catch(Exception e){}
        System.out.println(Thread.currentThread().getName()+"-----消費----"+this.name);
        this.falg=false;
        this.notifyAll();
    }

}

class Shengc implements Runnable{
    private Resource r;
    Shengc(Resource r){
        this.r=r;
    }
    public void run(){
        int x=0;
        while(true){
            r.set("+商品+");
        }

    }
}
class Xiaof implements Runnable{
    private Resource r;
    Xiaof(Resource r){
        this.r=r;
    }
    public void run(){
        while(true){            
            r.get();//r.outInfo();
        }

    }
}




/*    
public synchronized void setInfo(String name){
    if(falg)
        try{this.wait();}catch(Exception e){}
    this.name=name+"..."+count++;
    this.falg=true;
    this.notify();
}
public synchronized void outInfo(){
    if(!falg)
        try{this.wait();}catch(Exception e){}
    System.out.println(this.name);
    this.falg=false;
    this.notify();
}
*/

/*
if(x==0)
    r.setInfo("脈動");
else
    r.setInfo("哇哈哈");
x=(x+1)%2;
*/



---------- android培訓、 java培訓 、期待與您交流!----------
黑馬官網: http://edu.csdn.net/heima
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章