一、進(jìn)程相關(guā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)建線程池的消耗較高。 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ù)的需求
|
|
|