線程執行順序,其實就是看誰先争奪到資源,那麼有沒有辦法改變這種機制呢?
答案是,有的,但是也隻是幹預,并不是說不讓他們去争奪資源。
那就是使用了:線程優先級
同時我們也簡單了解一下 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除了用于線程同步、確定線程安全外,還可以保證線程間的 可見性 和 有序性。
*/
}