Synchronized關鍵字的使用

大前提:全部線程是沒有前後順序的,若是引入同步鎖,誰先得到對象鎖,誰先執行ide

 

線程實現方式:測試

1.繼承Thread類,重寫run方法;this

2.實現runnable接口,實現其run方法。線程

 

啓動方式:對象

    調用線程的start方法啓動線程,start方法爲線程準備好系統資源,而後調用run方法執行代碼邏輯。繼承

經常使用方法:接口

   Object對象方法:資源

     wait和notify方法:這兩個方法定義在Object類中,final方法,沒法重寫,這兩方法要求被調用時線程已得到對象的鎖,所以須要放在synchronized方法或塊中調用。當執行wait方法時,線程會釋放對象的鎖,線程會處於等待狀態;調用notify時,會隨機喚醒一個等待的線程(可是不會立馬被執行),此喚醒的線程與其餘線程競爭對象鎖。get

    notifyAll方法:也須要在靜態方法或靜態代碼塊中執行,會喚醒全部等待的線程跟其餘線程進行鎖的競爭;同步

    

當前線程對象的方法

    join:用於將當前線程插入到正在執行的線程,當前線程得到對象鎖並執行完後(銷燬後)纔會繼續進行原來正在執行線程未完成的操做。

 

靜態方法:

    Thread.sleep方法:會讓當前線程休眠指定毫秒時間,整個過程不會釋放對象鎖。

    Thread.yield方法:經當前線程從新置於就緒狀態,整個過程不會釋放對象鎖。

 

三種使用場景:

    1.修飾靜態方法:表示對類(Class對象)的枷鎖,在進入該靜態方法前,當前線程須要得到該類的鎖。

        一個線程訪問該Class對象的任何同步靜態方法,其餘線程沒法訪問該Class對象的任何同步方法。

    2.修飾普通方法:表示對類實例的加鎖,在進入普通方法前,當前線程須要得到該實例的鎖(若是是當前類的不一樣對象,則不會出現同步顯現);

    都一個普通方法用synchronized進行修飾,表示對對象加鎖,當一個線程調用該方法時,其餘線程沒法訪問該方法,指導第一個線程執行完或拋出異常釋放掉對象鎖,其餘線程纔有可能訪問該同步方法。

    若是一個對象有多個同步方法,當一個線程訪問某個同步方法時,其餘線程也是沒法訪問該對象的任何同步方法的。

    3.修飾代碼塊:表示對指定對象枷鎖,在進入代碼塊前,當前線程須要得到該指定對象的鎖

 

同步測試代碼以下:

/**
 * 同步關鍵字的使用
 * 全部線程是沒有優先級的(線程執行沒有前後順序),若是引入同步鎖,誰先得到對象鎖,誰先執行
 *
 * @author kevin
 * @email ly_triangle@126.com
 * @date 2018年3月8日
 */
public class SynchronizeDemo {

    /**
     * 同步靜態方法1
     */
    public synchronized static void synchronizedStaticMethod1() {
        try {
            System.out.println(Thread.currentThread().getName() + ":synchronizedStaticMethod1");
            Thread.sleep(2000l);
            System.out.println(Thread.currentThread().getName() + ":synchronizedStaticMethod1……");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 同步靜態方法2
     */
    public synchronized static void synchronizedStaticMethod2() {
        System.out.println(Thread.currentThread().getName() + ":synchronizedStaticMethod2");
    }

    /**
     * 同步普通方法1
     */
    public synchronized void synchronizedMethod1() {
        try {
            System.out.println(Thread.currentThread().getName() + ":synchronizedMethod1");
            Thread.sleep(2000l);
            System.out.println(Thread.currentThread().getName() + ":synchronizedMethod1……");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 同步普通方法2
     */
    public synchronized void synchronizedMethod2() {
        System.out.println(Thread.currentThread().getName() + ":synchronizedMethod2");
    }

    /**
     * 非同步普通方法1
     */
    public void method1() {
        try {
            System.out.println(Thread.currentThread().getName() + ":synchronizedMethod1");
            Thread.sleep(2000l);
            System.out.println(Thread.currentThread().getName() + ":synchronizedMethod1……");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 非同步普通方法2
     */
    public void method2() {
        System.out.println(Thread.currentThread().getName() + ":synchronizedMethod2");
    }

    /**
     * 同步代碼塊1
     */
    public void synchronizedCodes1() {
        try {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + ":synchronizedCodes1");
                Thread.sleep(2000l);
                System.out.println(Thread.currentThread().getName() + ":synchronizedCodes1……");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 同步代碼塊2
     */
    public void synchronizedCodes2() {
        System.out.println(Thread.currentThread().getName() + ":synchronizedCodes2 will begining……");
        synchronized (this) {
            System.out.println(Thread.currentThread().getName() + ":synchronizedCodes2");
        }
    }

    public static void main(String[] args) {

        /*測試非同步普通方法
        * 第二個線程不會等第一個結束就開始執行了
        */
        SynchronizeDemo demo = new SynchronizeDemo();
        new Thread(new Runnable() {
            @Override
            public void run() {
                demo.method1();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                demo.method2();
            }
        }).start();

       /* 測試同步靜態方法
       *第一個方法執行完畢後纔會執行第二個方法
       * 除非不是同一個類
       */
        // new Thread(new Runnable() {
        //     @Override
        //     public void run() {
        //         SynchronizeDemo.synchronizedStaticMethod1();
        //     }
        // }).start();
        //
        // new Thread(new Runnable() {
        //     @Override
        //     public void run() {
        //         SynchronizeDemo.synchronizedStaticMethod2();
        //     }
        // }).start();

        /*測試同步普通方法
        * 第一個方法執行完畢纔會執行第二個方法
        * 除非不是同一個對象
        */
        // SynchronizeDemo demo = new SynchronizeDemo();
        // new Thread(new Runnable() {
        //     @Override
        //     public void run() {
        //         demo.synchronizedMethod1();
        //     }
        // }).start();
        //
        // new Thread(new Runnable() {
        //     @Override
        //     public void run() {
        //         demo.synchronizedMethod2();
        //     }
        // }).start();

        /*測試同步代碼塊
        * 第一個代碼塊執行完纔會執行第二個代碼塊
        * 除非不是同一個對象
        */
        // SynchronizeDemo demo = new SynchronizeDemo();
        // new Thread(new Runnable() {
        //     @Override
        //     public void run() {
        //         demo.synchronizedCodes1();
        //     }
        // }).start();
        //
        // new Thread(new Runnable() {
        //     @Override
        //     public void run() {
        //         demo.synchronizedCodes2();
        //     }
        // }).start();
    }
}

 

wait和notify方法測試:

public class ThreadDemo {

    public synchronized void run() {
        try {
            for (int i = 0; i < 5; i++) {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + "  ::" + i);
                if (2 == i) {
                    this.wait();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void run1() {
        try {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "  " + i);
            }
            this.notify();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {

        ThreadDemo demo = new ThreadDemo();
        new Thread(new Runnable() {
            @Override
            public void run() {
                demo.run();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                demo.run1();
            }
        }).start();
    }
}

結果以下:
        Thread-0  ::0
        Thread-0  ::1
        Thread-0  ::2
        Thread-1  0
        Thread-1  1
        Thread-1  2
        Thread-1  3
        Thread-1  4
        Thread-0  ::3
        Thread-0  ::4

join方法測試:

public class ThreadJoinDemo {

    public synchronized void runDemo(String threadName, int i) {
        System.out.println(threadName + ":" + i);
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadJoinDemo demo = new ThreadJoinDemo();
        // 定義子線程
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    demo.runDemo(Thread.currentThread().getName(), i);
                }
            }
        });

        for (int i = 0; i < 5; i++) {
            demo.runDemo(Thread.currentThread().getName(), i);
            if (2 == i) {
                thread.start();

                //讓主線程釋放鎖,子線程得到對象鎖並執行完後纔會接着執行主線程未完的操做
                thread.join();
            }
        }
    }
}

結果以下:
        main 0
        main 1
        main 2
        Thread-0:0
        Thread-0:1
        Thread-0:2
        Thread-0:3
        Thread-0:4
        main 3
        main 4
相關文章
相關標籤/搜索