电竞比分网-中国电竞赛事及体育赛事平台

分享

Java面試-多線程技術(shù)

 Coder編程 2022-11-07 發(fā)布于北京

一、進(jìn)程相關(guān)概念:

1、程序是一個(gè)靜態(tài)的概念,進(jìn)程是執(zhí)行起來的程序,是一個(gè)動(dòng)態(tài)的概念。線程是進(jìn)程的一部分,一個(gè)進(jìn)程可以有一個(gè)或多個(gè)線程 2、進(jìn)程和線程最根本的區(qū)別在于:進(jìn)程是資源分配的單位,線程是調(diào)度和執(zhí)行的單位。線程可以看成是輕量級(jí)的進(jìn)程,線程之間切換開銷很小 3、多進(jìn)程:在操作系統(tǒng)中同時(shí)運(yùn)行多個(gè)任務(wù)(程序) 4、多線程:在同一應(yīng)用程序中有多個(gè)順序流同時(shí)執(zhí)行 5、每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(稱為:進(jìn)程上下文),進(jìn)程間的切換會(huì)有較大的開銷 6、系統(tǒng)會(huì)為每個(gè)進(jìn)程分配不同的內(nèi)存區(qū)域,但是不會(huì)為線程分配內(nèi)存。計(jì)算機(jī)軟硬件資源的分配與線程無關(guān),線程只能共享它所屬進(jìn)程的資源

二、Java中實(shí)現(xiàn)多線程的方式(三種):

1、通過繼承Thread類,重寫run方法,創(chuàng)建實(shí)例對(duì)象,調(diào)用start()方法來實(shí)現(xiàn)。

  需要注意的是:調(diào)用start()方法后,并不是立即執(zhí)行多線程代碼,而是使得該線程變?yōu)榭蛇\(yùn)行狀態(tài)(Runnable),具體什么時(shí)候執(zhí)行多線程代碼由操作系統(tǒng)決定

  這種方法的缺點(diǎn)是:如果類已經(jīng)繼承了一個(gè)類,則無法再繼承Thread類。因?yàn)镴ava是單繼承

2、實(shí)現(xiàn)Runnable接口,并實(shí)現(xiàn)該接口的run()方法【一般推薦使用此方法】。具體步驟如下:

 ?、僮远x類并實(shí)現(xiàn)Runnable接口,實(shí)現(xiàn)run方法

 ?、趧?chuàng)建Thread對(duì)象,用實(shí)現(xiàn)Runnable接口的對(duì)象作為參數(shù)實(shí)例化該Thread對(duì)象。如 Thread thread1 = new Thread(new TestThread2());

 ?、壅{(diào)用Thread的start方法

  這種方式也是開發(fā)中更多使用的方法。因?yàn)門hread類定義了多種可以被派生類使用或重寫,但是只有run方法是必須被重寫的,在run方法中實(shí)現(xiàn)這個(gè)線程的主要功能

3、實(shí)現(xiàn)Callable接口,重寫call方法。Callable接口與Runnable 接口類似,功能比runnable更強(qiáng)大,主要有以下三點(diǎn):

 ?、貱allable可以提供返回值,Runnable沒有

 ?、贑allable中的call方法可以拋出異常

三、線程狀態(tài)和生命周期

1、線程有 5 種狀態(tài):新生,就緒,運(yùn)行,死亡,阻塞。線程生命周期圖如下【好好理解,基本包含了線程整個(gè)生命周期的知識(shí)】:

 終止線程的方法:一般不使用JDK提供的stop/destory方法,他們本身也被棄用。通常使用一個(gè)boolean的標(biāo)記變量,當(dāng)這個(gè)變量置位false時(shí),終止線程的運(yùn)行

暫停線程的方法:使用sleep方法和yield方法。這兩種方法的區(qū)別:sleep方法是讓正在運(yùn)行的線程進(jìn)入阻塞狀態(tài),直到休眠期滿了,才進(jìn)入就緒狀態(tài)。yield方法則是讓線程直接進(jìn)入就緒狀態(tài)

        

 四、說說你對(duì)線程池的理解

  1、線程池簡(jiǎn)單來說就是一句話,用來對(duì)線程進(jìn)行一個(gè)集中統(tǒng)一的管理,以此來減少系統(tǒng)資源的消耗。

    因?yàn)閯?chuàng)建線程是非常耗時(shí)的, 多線程運(yùn)行時(shí)間,系統(tǒng)不斷的啟動(dòng)和關(guān)閉新線程,成本非常高,會(huì)過渡消耗系統(tǒng)資源,以及過渡切換線程的危險(xiǎn),從而可能導(dǎo)致系統(tǒng)資源的崩潰。

  2、線程池的優(yōu)勢(shì):

   ?、俳档拖到y(tǒng)資源消耗,提高系統(tǒng)響應(yīng)速度。通過重用已存在的線程,一個(gè)線程可執(zhí)行多個(gè)任務(wù),降低線程創(chuàng)建和銷毀造成的消耗;

   ?、诜奖憔€程并發(fā)數(shù)的管控。因?yàn)榫€程若是無限制的創(chuàng)建,可能會(huì)導(dǎo)致內(nèi)存占用過多而產(chǎn)生OOM(內(nèi)存使用過大),并且會(huì)造成cpu過度切換

   ?、厶峁└鼜?qiáng)大的功能,延時(shí)定時(shí)線程池

  3、線程池的參數(shù)有哪些:

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

    1、corePoolSize(線程池基本大小):當(dāng)向線程池提交一個(gè)任務(wù)時(shí),若線程池已創(chuàng)建的線程數(shù)小于corePoolSize,即便此時(shí)存在空閑線程,也會(huì)通過創(chuàng)建一個(gè)新線程來執(zhí)行該任務(wù),直到已創(chuàng)建的線程數(shù)大于或等于corePoolSize時(shí),(除了利用提交新任務(wù)來創(chuàng)建和啟動(dòng)線程(按需構(gòu)造),也可以通過 prestartCoreThread() 或 prestartAllCoreThreads() 方法來提前啟動(dòng)線程池中的基本線程。)

    2、maximumPoolSize(線程池最大大小):線程池所允許的最大線程個(gè)數(shù)。當(dāng)隊(duì)列滿了,且已創(chuàng)建的線程數(shù)小于maximumPoolSize,則線程池會(huì)創(chuàng)建新的線程來執(zhí)行任務(wù)。另外,對(duì)于無界隊(duì)列,可忽略該參數(shù)。

    3、keepAliveTime(線程存活保持時(shí)間)當(dāng)線程池中線程數(shù)大于核心線程數(shù)時(shí),線程的空閑時(shí)間如果超過線程存活時(shí)間,那么這個(gè)線程就會(huì)被銷毀,直到線程池中的線程數(shù)小于等于核心線程數(shù)。

    4、workQueue(任務(wù)隊(duì)列):用于傳輸和保存等待執(zhí)行任務(wù)的阻塞隊(duì)列。

    5、threadFactory(線程工廠):用于創(chuàng)建新線程。threadFactory創(chuàng)建的線程也是采用new Thread()方式,threadFactory創(chuàng)建的線程名都具有統(tǒng)一的風(fēng)格:pool-m-thread-n(m為線程池的編號(hào),n為線程池內(nèi)的線程編號(hào))。

    6、handler(線程飽和策略):當(dāng)線程池和隊(duì)列都滿了,再加入線程會(huì)執(zhí)行此策略。

  4、線程池流程:

  

  5、線程池為什么需要使用(阻塞)隊(duì)列?

    1、因?yàn)榫€程若是無限制的創(chuàng)建,可能會(huì)導(dǎo)致內(nèi)存占用過多而產(chǎn)生OOM,并且會(huì)造成cpu過度切換。

    2、創(chuàng)建線程池的消耗較高。
    3、線程池創(chuàng)建線程需要獲取mainlock這個(gè)全局鎖,影響并發(fā)效率,阻塞隊(duì)列可以很好的緩沖。

  6、Java提供了四個(gè)線程池的實(shí)現(xiàn)類:

   ?、?newSingleThreadExecutor:創(chuàng)建一個(gè)單線程的線程池,它只會(huì)用唯一的工作線程來執(zhí)行任務(wù),也就是相當(dāng)于單線程串行執(zhí)行所有任務(wù)。如果這個(gè)線程因?yàn)楫惓=Y(jié)束了,會(huì)有一個(gè)新的線程來替代它

    ② newFixedThreadPool:創(chuàng)建一個(gè)定長(zhǎng)的線程池,可控制線程的最大并發(fā)量,超出的線程會(huì)在隊(duì)列中等待。使用這個(gè)線程時(shí),要預(yù)先估算出線程的數(shù)量

    ③ newCachedThreadPool:用來創(chuàng)建一個(gè)可緩存的線程池,適用于負(fù)載較輕的場(chǎng)景,執(zhí)行短期異步任務(wù)。(可以使得任務(wù)快速得到執(zhí)行,因?yàn)槿蝿?wù)時(shí)間執(zhí)行短,可以很快結(jié)束,也不會(huì)造成cpu過度切換)

   ?、?nbsp;newScheduledThreadPool:創(chuàng)建一個(gè)定長(zhǎng)線程池,適用于執(zhí)行定時(shí)或者周期性任務(wù)的需求



 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多