天天看點

(七)線程的優先級Priority和關鍵詞:synchronized

線程執行順序,其實就是看誰先争奪到資源,那麼有沒有辦法改變這種機制呢?

答案是,有的,但是也隻是幹預,并不是說不讓他們去争奪資源。

那就是使用了:線程優先級

同時我們也簡單了解一下 synchronized 這個關鍵詞,了解一下他的特性和簡單用法等。

package com.zmkj.admin.test;

import lombok.SneakyThrows;

/**
 * 線程優先級
 *
 * 溫習一下線程的幾種狀态:
 * 建立(NEW)、可運作(RUNNABLE)、運作(RUNNING)、阻塞(BLOCKED)、死亡(DEAD)
 * 線程在:可運作 這個狀态的時候,其實是在等CPU的資源,這個時候不考慮設定了其他的因素,我們可以認為每個線程是公平競争資源的,誰争到誰運作。
 *
 * 這個其他因素 最直接的就是 "線程優先級",但是隻是說優先級高的,在競争的時候有資源,但也隻是有可能,這是個機率問題。
 * 但是這裡也需要面對另外一個問題"饑餓問題":優先級低的一直無法獲得資源,一直無法運作,最終"餓死了"。
 *
 *
 * 關鍵詞:synchronized
 * synchronized 的作用是實作線程間的同步。
 * 他的工作是對同步的代碼加鎖,是的每次,隻能有一個線程進入同步塊,進而保證線程間的安全性。
 *
 * 具體下面講哈
 *
 * @author sunminghao
 */
public class PriorityDemoAndSynchronized {

    public static class HightPriority extends Thread{
        static int count = 0;

        @SneakyThrows
        @Override
        public void run() {
            while (true){
                synchronized (PriorityDemoAndSynchronized.class){
                    count++;
                    if (count > 10000000){
                        System.out.println("HightPriority is complete.");
                        break;
                    }
                }
            }
        }
    }

    public static class LowPriority extends Thread{
        static int count = 0;

        @SneakyThrows
        @Override
        public void run() {
            while (true){
                synchronized (LowPriority.class){
                    count++;
                    if (count > 10000000){
                        System.out.println("LowPriority is complete.");
                        break;
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        Thread high = new HightPriority();
        LowPriority low = new LowPriority();
        high.setPriority(Thread.MAX_PRIORITY);
        low.setPriority(Thread.MIN_PRIORITY);
        low.start();
        high.start();
    }

    /**
     * 在Java 中,使用1 到 10 表示線程的優先級,一般的可使用内置的三個靜态标量表示。
     * 數字越大,優先級越高。
     */
    public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;

    /**
     *
     * 上面的栗子中,分别将兩個線程設定了不同的兩個優先級,執行内容相同,都是在count 累加到10000000 時,列印出提示語。(這個數值一定要大,不然效果不明顯)
     *
     * 注意,在對count 累加前,我們使用了synchronized 産生了一次資源競争,目的是使得優先級的差異表現得更加明顯。
     *
     * 大多數情況下,會優先輸出 "HightPriority is complete."  但是記住了 這個也不是絕對的!!!
     */


    /**
     * synchronized 關鍵詞
     * 簡單的說就是,保證 線程 A 在寫入時,線程B 不僅不能寫,同時也不能讀。
     *
     * 之前我們的例子裡面有用到 volatile 關鍵詞,
     * volatile 雖然確定了一個線程修改了資料後,其他線程能夠看到這個改動,但是 他也隻是改善了線程的錯誤率,但并不是解決。
     * 在多線程方面,存在資源競争的現象,當 A 線程 讀取到了 一個資料 count 值後,進行了加 1 操作,但是在 A 讀取的同時,
     * B線程也讀取到了 count = 1, 之後進行了加 2 ,那麼,你說最後 count 是應該等于幾呢?
     * 等于 2 嗎? 等于 3 嗎? 等于 5 嗎?
     * 其實正确的結果是不是應該 是  1 + 1 + 2 = 4
     * 怎麼做到呢?就需要 synchronized 保證了
     *
     * 他保證了 ----  線程安全
     * 多種用法這裡做一下簡單的整理:
     *
     * 1、指定加鎖對象:對給定對象加鎖,進入同步代碼前要獲得給定對象的鎖。
     * 2、直接作用于執行個體方法:相當于對目前執行個體加鎖,進入同步代碼前要獲得目前執行個體對鎖。
     * 3、直接作用于靜态方法:相當于對目前類加鎖,進入同步代碼前要獲得目前類的鎖。
     *
     * TODO synchronized除了用于線程同步、確定線程安全外,還可以保證線程間的 可見性 和 有序性。
     */
}