Java多線程(二)

Java多線程(一):
https://blog.csdn.net/Veer_c/article/details/103842078
Java多線程(二):
https://blog.csdn.net/Veer_c/article/details/103842263
Java多線程(三):
https://blog.csdn.net/Veer_c/article/details/103842317
Java多線程(四):
https://blog.csdn.net/Veer_c/article/details/103842602

案例:利用匿名內部類,啓動多個線程,驗證單例設計模式之懶漢式所存在的缺陷,

public class SingleIntanceDemo {
    //私有化構造
    private SingleIntanceDemo(){}
    private static SingleIntanceDemo instance = null;
    public  static SingleIntanceDemo getInstance(){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (instance==null) {
            instance = new SingleIntanceDemo();
        }
        return instance;
    }
}
public class Test {
    public static void main(String[] args) {
        //啓動第一個線程
        new Thread(){
            @Override
            public void run() {                
            	System.out.println(SingleIntanceDemo.getInstance());
                //com.edu_12.SingleIntanceDemo@2d7fc1e7
            }
        }.start();
        //啓動第二個線程
        new Thread(){
            public void run() {              
            	System.out.println(SingleIntanceDemo.getInstance());
                //com.edu_12.SingleIntanceDemo@2a8b83e3
            };
        }.start();
    }
}

當我們利用多線程來驗證單例模式的時候,發現倆個對象的地址值不同,即不是同一個對象,我們可以利用同步方法來改進
在創建對象的方法上加上 synchronized關鍵字就可以
(9)JDK5的Lock鎖,我們之前造的所有的鎖都沒有手動釋放鎖
static Lock lock = new ReentrantLock();
上枷鎖:lock.lock();
釋放鎖:lock.unlock();
可以讓我們明確的知道在哪裏加鎖和釋放鎖。
依然寫一個賣票的案例,用lock枷鎖釋放鎖,
爲了保證我們創建的鎖一定會被釋放,用一下代碼進行改進
try{….}finally{……}

public class MyThread implements Runnable{
    //定義100張票
    int ticket = 100;
    Object obj = new Object();
    //創建一個鎖
    Lock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true) {
            try{
                //加上鎖,獲取鎖
                lock.lock();
                if (ticket>0) {
                        //考慮到實際的生活中,我們需要給每一個線程加入一定的延遲,模擬一下這種效果
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"正在出售第:"+ticket--+"張票");
                    }
            }finally{
                //這裏面的代碼一定會被執行
                //釋放鎖
                lock.unlock();
            }
            }
    }
}
public class Test {
    public static void main(String[] args) {
        //創建MyThread對象
        MyThread mt = new MyThread();
        //創建三個窗口
        Thread t1 = new Thread(mt);
        Thread t2 = new Thread(mt);
        Thread t3 = new Thread(mt);
        //給每一個窗口設置姓名
        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");
        //開啓窗口進行售票
        t1.start();
        t2.start();
        t3.start();
    }
}

死鎖問題:
同步嵌套,鎖裏面套了一個鎖,出現同步嵌套

package com.edu_14;
public class DieThread extends Thread{
    boolean flag;
    //提供一個有參構造
    public DieThread(boolean flag){
        this.flag = flag;
    }
    @Override
    public void run() {
        if (flag) {
            synchronized (MyLock.objA) {
                System.out.println("if"+"objA");
                synchronized (MyLock.objB) {
                    System.out.println("if"+"objB");
                }
            }
        }else {
            synchronized (MyLock.objB) {
                System.out.println("else"+"objB");
                synchronized (MyLock.objA) {
                    System.out.println("else"+"objA");
                }
            }
        }
    }
}
package com.edu_14;
public abstract class MyLock {
    //定義兩個鎖
    public static final Object objA = new Object();
    public static final Object objB = new Object();
}
package com.edu_14;
public class Test {
    public static void main(String[] args) {
        //創建兩個線程,分別設置不同的布爾值
        DieThread dt = new DieThread(true);
        DieThread dt2 = new DieThread(false);
        //開啓兩個線程
        dt.start();
        dt2.start();
    }
}

線程等待和喚醒機制:waitThread,NotifyThread,MyLock,Test
鎖對象調用wait() 鎖對象調用notify()

package com.edu_15;
public abstract class MyLock {
    public static final Object obj = new Object();
}
package com.edu_15;
public class WaitThread extends Thread{
    @Override
    public void run() {
        synchronized (MyLock.obj) {
            //讓等待線程處於等待狀態
            try {
                MyLock.obj.wait();//當線程處於等待狀態的時候,線程就不會繼續往下執行了
                                  //線程在處於等待的時候,會釋放掉自己手中的鎖
                                 //sleep()這個方法,在線程休息的時候會釋放鎖碼?
                                //答:不會
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("我被喚醒了");
    }
}
package com.edu_15;
public class NotifyThread extends Thread{
    @Override
    public void run() {
        synchronized (MyLock.obj) {
            //喚醒等待線程
            MyLock.obj.notify();//喚醒正在等待的線程,喚醒的等待線程的鎖對象,必須和等待線程的鎖對象一致
        }
    }
}
package com.edu_15;
/*  (11)線程等待和喚醒機制(案例演示:waitThread,NotifyThread,MyLock,Test)
        鎖對象調用wait():線程的等待
        鎖對象調用notify():線程的喚醒
 *    注意:
        wait和sleep的區別
        線程等待,在等待的同時釋放鎖,而sleep()方法在執行的過程中是不會釋放鎖的    */
public class Test {
    public static void main(String[] args) {
        //創建等待線程,讓等待線程處於一個等待狀態
        WaitThread wt = new WaitThread();
        wt.start();
        //睡上5秒鐘之後喚醒等待線程
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //創建喚醒線程對象
        NotifyThread nt = new NotifyThread();
        nt.start();
    }
}

注意:wait和sleep的區別:
線程等待,在等待的同時釋放鎖,而sleep()方法在執行的過程中是不會釋放鎖的

Java多線程(一):
https://blog.csdn.net/Veer_c/article/details/103842078
Java多線程(二):
https://blog.csdn.net/Veer_c/article/details/103842263
Java多線程(三):
https://blog.csdn.net/Veer_c/article/details/103842317
Java多線程(四):
https://blog.csdn.net/Veer_c/article/details/103842602

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章