Java從菜鳥到精通(10)

來源:互聯網
上載者:User

單例設計模式。
1、餓漢式

/*
  class  Single{
    //寫上final更嚴謹,s永遠指向Single()
    private static [final] Single s=new

Single();
    private Single(){}
    public static Single getInstance(){
        return s;
    }
}

*/
***********************
************************
************************
2、懶漢式*****面試****
//在多線程訪問時,會產生安全隱患
1.懶漢式與餓漢式有什麼不同?
懶漢式的特點:用於執行個體的延時載入
2.執行個體的延時載入有沒有問題?
有。如果多線程訪問時,會出現安全問題。
3.怎麼解決?
可以使用同步來解決。而加同步的方式,用同步函

數或者同步代碼塊都行,但是稍微有些低效。
4.怎麼解決低效?
用雙重判斷的形式來解決低效問題。
5.加同步的時候,使用的鎖是哪一個?
該類所屬的位元組碼物件導向。
6.筆試題:寫出一個延時載入的單例設計模式執行個體

。(如下)
class Single{
    private static Single s=null;
    private Single(){}
    public static [synchronized] Single

getInstance(){
    if(s==null){
    synchronized(Single.class){
     if(s==null){
        //--> Thread A
        s=new Single();
    }    
    }
}
     return s;
    }
}

死結。
就是說,A持有一個鎖,B也持有一個鎖,A要到B裡

面去運行,要拿B的鎖,而B要到A裡面運行,必須

拿A的鎖,這樣會出現,A不放自己的鎖,去B裡面

運行,B也不放自己的鎖,到A裡面去運行,誰都不

放,就導致死結。這樣出現的情況是:程式就不會

運行了。
最可能出現死結的是:同步中嵌套同步,而鎖不同


************面試******
請寫一個死結的程式?
死結例子:
class Test implements Runnable
{
    private boolean flag;
    Test(boolean flag){
        this.flag=flag;
    }       
    public void run(){
    
        if(flag){
while(true){
            synchronized

(MyLock.locka){
            syso("if TestA")
            synchronized

(MyLock.lockb){
            syso("else testB");
            }
            }
}
        }else {
        while(true){
            synchronized

(MyLock.lockb){
            syso("if TestB");
            synchronized

(MyLock.locka){
            syso("else testA");
            }
            }
        }
    }
}
}

class MyLock
{
    static Object locka=new Object();
    static Object lockb=new Object();
    
}

class DeadLockTest{

    public static void main(String []

args){
Thread t1=new Thread(new Test(true));
Thread t2=new Thread(new Test(flase));
t1.start();
t2.start();
    }
}

多線程間的通訊
常式
---input-->資源---output--->
思考1:
wait(),notify(),notifyAll(),用來操作線程為什

麼定義在Object類中?
1、這些方法存在與同步中。
2、使用這些方法時必須要標識所屬的同步鎖。
3、鎖可以是任意對象,所以任意對象調用的方法

一定定義Object類中。

思考2:
wait(),sleep()有什麼區別?
wait():釋放資源,釋放鎖。
sleep():釋放資源,不釋放鎖。

線程間通訊:
其實就是多個線程在操作同一個資源。但是操作的

動作不同。

class Res{
    String name;
    String sex;
}
class Input implements Runnable
{    
    private Res r;
    //Object obj=new Object();
    Input(Res r){
        this.r=r;
    }
    public void run(){
        int x=0;
        while(true)
        {
//資源是唯一的所以就傳r
    synchronized(r){
        if(x==0){
        r.name="mike";
        r.sex="man"
        }else{
        r.name="XX";
        r.sex="X"
        }
        x=(x+1)%2;
        }
}
    }
}
class Output  implements Runnable
{
    private Res r;
    //Object obj=new Object();
    Onput(Res r){
        this.r=r;
    }
    public void run(){
        while(true)
        {
    synchronized(r){
        syso(r.name+r.sex);
    }
        }
    }

}

class InputOutputDemo
{
    public static void main(String []

args)
    {
    Res r=new Res();
    
    Input in=new Input(r);
    Output out=new Output(r);
    
    Thread t1=new Thread(in);
    Thread t2=new Thread(out);
    
    t1.start();
    t2.start();
    }
}

****線程間通訊--------等待喚醒機制
例題:
class Res{
    String name;
    String sex;
    boolean flag=false;
}
class Input implements Runnable
{    
    private Res r;
    //Object obj=new Object();
    Input(Res r){
        this.r=r;
    }
    public void run(){
        int x=0;
        while(true)
        {
//資源是唯一的所以就傳r
    synchronized(r){
    if(r.flag)
    try{r.wait();}catch(){}//放棄了執行

資格
    //放在線上程池裡
        if(x==0){
        r.name="mike";
        r.sex="man"
        }else{
        r.name="XX";
        r.sex="X"
        }
        x=(x+1)%2;
    r.flag=true;
    r.notify();
//喚醒線程池裡線程,通常喚醒第一個被喚醒的
        }
}
    }
}
class Output  implements Runnable
{
    private Res r;
    //Object obj=new Object();
    Onput(Res r){
        this.r=r;
    }
    public void run(){
        while(true)
        {
    synchronized(r){
        if(!r.flay)
        try{r.wait();}catch(){}
        syso(r.name+r.sex);
        r.flag=false;
        r.notify();
    }
        }
    }

}

class InputOutputDemo
{
    public static void main(String []

args)
    {
    Res r=new Res();
    
    Input in=new Input(r);
    Output out=new Output(r);
    
    Thread t1=new Thread(in);
    Thread t2=new Thread(out);
    
    t1.start();
    t2.start();
    }
}
------------------------------
wait():
notify():
notifyAll():
都使用在同步中,因為要對持有監視器(鎖)的線

程操作。
所以要使用在同步中,因為只有同步才具有鎖。

為什麼這些操作線程的方法要定義在Object類中呢


因為這些方法在操作同步中線程時,都必須要標識

他們所操作線程只有的鎖,只有同一個鎖上的被等

待線程,可以被同一個鎖上notify喚醒。
不可以對不同鎖中的線程進行喚醒。

也就是說,等待和喚醒必須是同一個鎖。
而鎖可以是任意對象,所以可以被任意對象調用的

方法定義在Object類中。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.