Java線程相關知識

一恭理、相關概念:

進程:是指一個內存中運行的應用程序,每個進程都有一個獨立的內存空間
線程:

  • 是進程中的一個執(zhí)行路徑丰涉,共享一個內存空間,線程之間可以自由切換斯碌,并發(fā)執(zhí)行一死,一個進程最少有一個線程
  • 線程時間上是在進程的基礎之上進一步劃分,一個進程啟動之后傻唾,里面的若干執(zhí)行路徑又可以劃分成若干個線程
  • 每個線程都擁有自己的椡洞龋空間,但是會共用一份堆內存

同步:排隊執(zhí)行冠骄,效率低但是安全
異步:同時執(zhí)行伪煤,效率高但是數據不安全

并發(fā):指兩個或多個事件在同一個時間段內發(fā)生
并行:指兩個或多個事件在同一時刻發(fā)生(同時發(fā)生)

線程的生命周期:

  • NEW:尚未啟動的線程
  • Runnable:在Java虛擬機中執(zhí)行的線程
  • Blocked:被阻塞等待監(jiān)視器鎖定的線程
  • Waiting:無期限等待另一個線程執(zhí)行特定操作的線程
  • Timed_Waiting:正在等待另一個線程執(zhí)行最多指定等待時間的操作的線程
  • Terminated:已經退出的線程

二、多線程技術:

兩種開啟多線程的方式:

  1. 繼承Thread類的方式開啟:
    內部重寫run方法凛辣,run方法就是線程要執(zhí)行的任務方法带族,是一條新的執(zhí)行路徑,需要通過調用start方法觸發(fā)
  2. 實現(xiàn)Runnable接口的方式開啟:(較為常用)
    實現(xiàn)接口的抽象方法run()蟀给,在主線程中,創(chuàng)建一個任務對象阳堕,再創(chuàng)建一個線程跋理,將任務對象傳入,調用線程的start方法觸發(fā)

聲明實現(xiàn)Runnable接口的優(yōu)點:

  • 通過創(chuàng)建任務恬总,然后給線程分配的方式來實現(xiàn)的多線程前普,更適合多個線程同時執(zhí)行相同任務的情況
  • 可以避免單繼承所帶來的局限性
  • 任務與線程本身是分離的,提高了程序的健壯性壹堰,減少程序間的耦合
  • 后續(xù)學習的線程池技術拭卿,接收Runnable類型的任務,不接收Thread類型的線程

三贱纠、線程安全問題:

解決方案1:
隱式鎖峻厚,同步代碼塊
格式:

synchronized(鎖對象) {
                        要執(zhí)行的代碼;
                     }

解決方案2:
隱式鎖谆焊,同步方法(可以被static修飾)

  • 若不是靜態(tài)惠桃,則鎖對象為調用同步方法的對象
  • 若為靜態(tài),則鎖對象為==類名.Class==

Synchroized關鍵字特性:

  1. 原子性(互斥性):實現(xiàn)多線程的同步機制,使得鎖內代碼的運行必須先獲得對應的鎖辜王,運行完后自動釋放對應的鎖
  2. 內存可見性:在同一鎖的情況下劈狐,synchronized鎖內的代碼保證變量的可見性
  3. 可重入性:當一個線程獲取一個對象的鎖,再次請求改對象的鎖時呐馆,是可以再次獲取該對象的鎖的

注意:如果在synchronized鎖內發(fā)生異常肥缔,鎖將會被釋放

總結:

  • synchronized會自動釋放鎖
  • synchronized方法與synchronized(this)代碼塊,鎖定的都是當前的對象汹来,不同的只是同步代碼的范圍
  • 靜態(tài)synchronized方法與synchronized(class)代碼塊续膳,鎖定的都是Class鎖,與對象鎖不是同一個鎖俗慈,兩者同時使用可能會出現(xiàn)異步執(zhí)行的效果
  • 盡量不要使用synchronized(String)姑宽,因為String的實際鎖為String的常量池對象,多個值相同的String對象可能持有同一個鎖

解決方案3:
顯式鎖 Lock 子類 ReentrantLock

private java.util.concurrent.locks.Lock lock = new ReentrantLock();
public void method() {
        try {
            lock.lock();
            //獲取到鎖lock的同步塊
        } finally {
            lock.unlock();    //釋放鎖lock
        }
}

優(yōu)點:

  • 要求程序員手動釋放鎖闺阱,且一定要在finally代碼塊中釋放
  • 具有公平策略的選擇炮车,防止一個線程結束后立即重新獲得運行權,在構造對象時酣溃,傳入true參數:Lock lock = new ReentrantLock(true):
  • 可以在獲取鎖的時候進行有條件的獲取瘦穆,可以設置等待時間,避免產生死鎖問題:tryLock()和 tryLock(long timeout, TimeUnit unit)
  • 可以獲取鎖的各種信息赊豌,可以用來監(jiān)控鎖的各種狀態(tài)
  • 可以利用Condition中的singal方法扛或,實現(xiàn)對需要喚醒線程的精確控制

四、帶返回值的線程:

//1. 編寫實現(xiàn)類碘饼,實現(xiàn)Callable接口熙兔,并重寫call方法:
class Mycallable implements Callable<T> {
          @Override
          public <T> call() throws Exception {
                 return T;
          }
}

//2. 創(chuàng)建FutureTask對象,并傳入第一部編寫的Callable實現(xiàn)類對象
FutureTask<Integer> future = new FutureTask<>(new Mycallable());

//3. 通過Thread艾恼,啟動線程
new Thread(future).start();

五住涉、線程池:

意義:如果并發(fā)的線程數量很多,并且每個線程都僅僅執(zhí)行一個很短時間的任務钠绍,那么此時頻繁創(chuàng)建線程就會大大降低系統(tǒng)的效率舆声。線程池就是一個可以容納多個線程的容器,池中的線程可以反復使用柳爽,省去了頻繁創(chuàng)建線程對象的操作媳握,節(jié)省了大量的時間和資源

好處:

  • 降低資源消耗
  • 提高響應速度
  • 提高線程的可管理性

分類:

  • 緩存線程池:(長度無限制)

    1. 判斷線程池是否存在空閑線程
    2. 存在則使用
    3. 不存在則創(chuàng)建線程,并放入線程池磷脯,然后使用
      適用:執(zhí)行很多短期異步的小程序或者負載較輕的服務器
public static void cacheThreadPool() {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 1; i <= 10; i++) {
            final int ii = i;
            try {
                Thread.sleep(ii * 1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            cachedThreadPool.execute(()->out.println("線程名稱:" + Thread.currentThread().getName() + "蛾找,執(zhí)行" + ii));
        }

    }
  • 定長線程池:(長度是指定的數值)

    1. 判斷線程池是否存在空閑線程
    2. 存在則使用
    3. 不存在空閑線程,且線程池未滿的情況下赵誓,則創(chuàng)建線程并放入線程池腋粥,然后使用
    4. 不存在空閑線程晦雨,且線程池已滿的情況下,則等待線程池存在空閑線程
      適用:執(zhí)行長期的任務隘冲,性能會好很多
public static void fixTheadPoolTest() {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int ii = i;
            fixedThreadPool.execute(() -> {
                out.println("線程名稱:" + Thread.currentThread().getName() + "闹瞧,執(zhí)行" + ii);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }
  • 單線程線程池:

    1. 判斷線程池的線程是否空閑
    2. 空閑則使用
    3. 不空閑,則等待池中的單個線程空閑后使用
      適用:一個任務一個任務執(zhí)行的場景
public static void singleTheadPoolTest() {
        ExecutorService pool = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int ii = i;
            pool.execute(() -> out.println(Thread.currentThread().getName() + "=>" + ii));
        }
    }
  • 周期性任務定長線程池:

    1. 判斷線程池是否存在空閑線程
    2. 存在則使用
    3. 不存在空閑線程展辞,且線程池未滿的情況下奥邮,則創(chuàng)建線程,并放入線程池罗珍,然后使用
    4. 不存在空閑線程洽腺,且線程池已滿的情況下,則等待線程池存在空閑線程
      周期性任務執(zhí)行時:定時執(zhí)行覆旱,當某個時機出發(fā)時蘸朋,自動執(zhí)行某任務
      適用:周期性執(zhí)行任務的場景
    • 定時執(zhí)行一次:
      1. 參數1:定時執(zhí)行的任務
      2. 參數2:時長數字
      3. 參數3:時長數字的時間單位,TimeUnit的常量指定
    • 周期執(zhí)行的任務:
      1. 參數1:任務
      2. 參數2:延遲時長數字(第一次執(zhí)行在什么時間后)
      3. 參數3:周期時長數字(每隔多久執(zhí)行一次)
      4. 參數4:時長數字的單位
public static void sceduleThreadPool() {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        Runnable r1 = () -> out.println("線程名稱:" + Thread.currentThread().getName() + "扣唱,執(zhí)行:3秒后執(zhí)行");
        scheduledThreadPool.schedule(r1, 3, TimeUnit.SECONDS);
        Runnable r2 = () -> out.println("線程名稱:" + Thread.currentThread().getName() + "藕坯,執(zhí)行:延遲2秒后每3秒執(zhí)行一次");
        scheduledThreadPool.scheduleAtFixedRate(r2, 2, 3, TimeUnit.SECONDS);
        Runnable r3 = () -> out.println("線程名稱:" + Thread.currentThread().getName() + ",執(zhí)行:普通任務");
        for (int i = 0; i < 5; i++) {
            scheduledThreadPool.execute(r3);
        }
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末噪沙,一起剝皮案震驚了整個濱河市炼彪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌正歼,老刑警劉巖辐马,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異局义,居然都是意外死亡喜爷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門萄唇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贞奋,“玉大人,你說我怎么就攤上這事穷绵。” “怎么了特愿?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵仲墨,是天一觀的道長。 經常有香客問我揍障,道長目养,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任毒嫡,我火速辦了婚禮癌蚁,結果婚禮上幻梯,老公的妹妹穿的比我還像新娘。我一直安慰自己努释,他們只是感情好碘梢,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伐蒂,像睡著了一般煞躬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逸邦,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天恩沛,我揣著相機與錄音,去河邊找鬼缕减。 笑死雷客,一個胖子當著我的面吹牛,可吹牛的內容都是我干的桥狡。 我是一名探鬼主播搅裙,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼总放!你這毒婦竟也來了呈宇?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤局雄,失蹤者是張志新(化名)和其女友劉穎甥啄,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體炬搭,經...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蜈漓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了宫盔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片融虽。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖灼芭,靈堂內的尸體忽然破棺而出有额,到底是詐尸還是另有隱情,我是刑警寧澤彼绷,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布巍佑,位于F島的核電站,受9級特大地震影響寄悯,放射性物質發(fā)生泄漏萤衰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一猜旬、第九天 我趴在偏房一處隱蔽的房頂上張望脆栋。 院中可真熱鬧倦卖,春花似錦、人聲如沸椿争。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丘薛。三九已至嘉竟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間洋侨,已是汗流浹背舍扰。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留希坚,地道東北人边苹。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像裁僧,于是被迫代替她去往敵國和親个束。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345