国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

wordpress實例站百度推廣托管公司

wordpress實例站,百度推廣托管公司,分析某個網(wǎng)站建設,深圳教育網(wǎng)站建設目錄 前言 一、什么是線程池 1.引入線程池的原因 2.線程池的介紹 二、標準庫中的線程池 1.構造方法 2.方法參數(shù) (1)corePoolSize 與 maximumPoolSize (2)keepAliveTime 與 unit (3)workQueue&am…

目錄

·前言

一、什么是線程池

1.引入線程池的原因

2.線程池的介紹

二、標準庫中的線程池

1.構造方法

2.方法參數(shù)

(1)corePoolSize?與?maximumPoolSize?

(2)keepAliveTime?與?unit

(3)workQueue(任務隊列)

(4)threadFactory(線程工廠)

(5)?handler(拒絕策略)

3.使用標準庫中線程池

三、實現(xiàn)線程池

·結尾


·前言

? ? ? ? 在我們學習編程知識過程中一定聽說過很多池,比如常量池,還有在我前面?MySql?專欄中?JDBC 編程里提到的數(shù)據(jù)庫連接池,以及本篇文章要為大家介紹的線程池,所謂的這些池作用其實都差不多,都是提前把要用的對象創(chuàng)建好,然后把用完的對象不立即釋放留著以備下次使用,這樣就可以起到提高效率的作用,本篇文章就會為大家介紹一下什么是線程池,在我們?Java?標準庫中的線程池是什么樣的,以及使用?Java?代碼來實現(xiàn)一個簡單的線程池讓大家能更清晰的認識線程池,那么就開始本篇文章的介紹內容吧。

一、什么是線程池

1.引入線程池的原因

? ? ? ? 在我們最開始,引入進程的概念就能夠解決并發(fā)編程的問題,后來由于頻繁創(chuàng)建銷毀進程帶來的開銷太大,從而引入了線程(輕量級進程)這樣的概念,使用復用資源的方式來提高創(chuàng)建銷毀的效率,但是如果創(chuàng)建和銷毀線程的頻率也進一步提高呢?此時,線程的創(chuàng)建和開銷也就不能無視了。

? ? ? ? 為了優(yōu)化線程的創(chuàng)建與銷毀的效率,有下面兩種解決方案:

  1. 引入輕量級線程,也稱為“協(xié)程”;
  2. 使用線程池。

? ? ? ? ?為什么協(xié)程可以優(yōu)化線程的開銷與銷毀,這是因為協(xié)程的本質是我們在用戶態(tài)代碼中進行調度,不是靠內核的調度器調度的,這樣就可以節(jié)省很多調度上的開銷,此時,我們代碼中創(chuàng)建上千個線程會卡死,但是創(chuàng)建上千個協(xié)程就沒什么事了。

? ? ? ? 雖然協(xié)程有很多的好處,但是在?Java?中不是很推薦用上述做法來優(yōu)化線程的創(chuàng)建與銷毀,這是因為引入?yún)f(xié)程會引入額外的復雜性,使用協(xié)程可能不是很穩(wěn)定,協(xié)程的調試比較困難……所以相比于協(xié)程,使用線程池對于優(yōu)化線程的創(chuàng)建與銷毀會更好一些,那么下面就進一步介紹一下線程池是什么吧。

2.線程池的介紹

? ? ? ? 線程池就是要把使用的線程提前創(chuàng)建好,用完了一個線程也不要直接釋放,而是放到線程池中以備下次的使用,這樣就節(jié)省了線程創(chuàng)建與銷毀的開銷,因為在這使用線程的過程中,并沒有真的頻繁創(chuàng)建和銷毀線程,只是從線程池中取線程使用,用完還會放回去。

? ? ? ? 那么為什么從線程池中取線程就比從系統(tǒng)中申請更高效呢?這就好比你讓室友幫你取快遞,室友答應幫你取,但是什么時候給你取回來,他在幫你取快遞的途中會不會做一些什么事情都是不確定的,相比之下,你自己去取快遞,就會更高效,通過上面的例子,我們可以得到以下結論:

  • 從線程池中取線程是純用戶態(tài)代碼,是可控的;
  • 通過系統(tǒng)申請創(chuàng)建線程,需要系統(tǒng)內核來完成,這是不可控的。

二、標準庫中的線程池

1.構造方法

? ? ? ? 在?Java?標準庫中?ThreadPoolExecutor?這個類就是用來創(chuàng)建線程池的,關于這個類,它的構造方法有很多的參數(shù),由我來給大家介紹一下,下面是這個類的幾個構造方法,如下圖所示:

? ? ? ? 如上圖,ThreadPoolExecutor?一共涉及到四個構造方法,這里我只對第四個構造方法的每個參數(shù)進行一個介紹,這是因為,最后一個構造方法的參數(shù)是最全的,可以這么理解,介紹完第四個構造方法的各個參數(shù),其余三個構造方法也就都包含了。

2.方法參數(shù)

(1)corePoolSize?與?maximumPoolSize?

? ? ? ? 在標準庫提供的線程池中,持有的線程個數(shù)并不是一成不變的,它會根據(jù)當前的任務量來自適應當前線程的個數(shù)(任務數(shù)量很多,就會多創(chuàng)建幾個線程,任務量比較少,就會少創(chuàng)建幾個線程),在構造方法中的前兩個參數(shù)?int?corePoolSize?代表線程池中核心線程數(shù)有多少也就是一個線程池中最少得有多少個線程,int?maximumPoolSize?代表了線程池中最大線程數(shù)是多少也就是一個線程池中最多能有多少個線程。

(2)keepAliveTime?與?unit

? ? ? ? 第三個參數(shù):long?keepAliveTime?代表的意思就是線程池中除了核心線程外的線程的保持存活時間,在上面介紹了標準庫中的線程池是根據(jù)當前的任務量來自適應當前線程的個數(shù),這個參數(shù)就是自適應實現(xiàn)的一個重要標準,keepAliveTime?可以記錄除了核心線程外的線程空閑的時間,如果這些線程的空閑時間超過了?keepAliveTime 的值就會自動銷毀這些線程,來達到一個自適應的效果,這里的第四個參數(shù):TimeUnit?unit 就是搭配?keepAliveTime?這個參數(shù)的,unit?代表的是時間單位,它可以是 s、min、ms、hour……也就代表了空閑時間 keepAliveTime?的時間單位。

(3)workQueue(任務隊列)

? ? ? ? 第五個參數(shù):BlockingQueue了<Runnable> workQueue?代表線程池中可以有很多個任務,這里使用?Runnable?來作為描述任務的主體,線程池中線程不斷從這個阻塞隊列中取任務來執(zhí)行。

(4)threadFactory(線程工廠)

? ? ? ? 第六個參數(shù):ThreadFactory?threadFactory?意思是線程工廠,通過這個工廠類就可以來創(chuàng)建線程對象(Thread?對象),這個類里提供了方法,方法中封裝了?new?Thread?這樣的操作,并且同時給?Thread?設置了一些屬性,由此就構成了 ThreadFactory?線程工廠。?

? ? ? ? 這里的線程工廠也用到了一種設計模式:工廠模式,它是通過專門的“工廠類”/“工廠對象”來創(chuàng)建指定對象,那么為什么使用工廠模式呢?我們來看下面的一個代碼示例:

// 表示平面上的一個點
class Point {// 笛卡爾坐標系 x 與 yprivate double x;private double y;// 極坐標系 r 與 aprivate double r;private double a;// 通過笛卡爾坐標系來構造這個點public Point(double x, double y) {setX(x);setY(y);}// 通過極坐標系來構造這個點public Point(double r, double a) {setR(r);setA(a);}public double x() {return x;}public void setX(double x) {this.x = x;}public double y() {return y;}public void setY(double y) {this.y = y;}public double r() {return r;}public void setR(double r) {this.r = r;}public double a() {return a;}public void setA(double a) {this.a = a;}
}

? ? ? ? 不知道大家看完上面的代碼有沒有發(fā)現(xiàn)什么問題,這里的問題就在于?Point?這個類的兩個構造方法不構成重載,它們的參數(shù)列表是一樣的,如下圖所示:?

? ? ? ? 想必我們都知道,使用笛卡爾坐標和使用極坐標都可以表示一個點,并且這兩個表示方法并不相同,想通過同一個類的構造方法來用這兩種不同的方式表示不同的點就違背了 Java 的語法規(guī)則,為了解決上述的問題,就引入了“工廠模式”。

? ? ? ? 工廠模式的基本邏輯就是使用普通方法來創(chuàng)建對象,在普通方法中把構造方法進行封裝,利用工廠模式修改后的代碼及運行結果如下所示:

// 表示平面上的一個點
class Point {// 笛卡爾坐標系 x 與 yprivate double x;private double y;// 極坐標系 r 與 aprivate double r;private double a;// 通過笛卡爾坐標系來構造這個點public static Point makePointByXY(double x, double y) {Point point = new Point();point.setX(x);point.setY(y);return point;}// 通過極坐標系來構造這個點public static Point makePointByRA(double r, double a) {Point point = new Point();point.setR(r);point.setA(a);return point;}public double x() {return x;}public void setX(double x) {this.x = x;}public double y() {return y;}public void setY(double y) {this.y = y;}public double r() {return r;}public void setR(double r) {this.r = r;}public double a() {return a;}public void setA(double a) {this.a = a;}
}
public class PointFactory {public static void main(String[] args) {Point point1 = Point.makePointByXY(3,4);Point point2 = Point.makePointByRA(3,30);System.out.println("point1 的笛卡爾坐標:->(" + point1.x() + "," + point1.y() + ")");System.out.println("point2 的極坐標:->(" + point2.r() + "," + point2.a() + ")");}
}

?

?????????此時,利用工廠模式就可以創(chuàng)建出兩個方式表示的點,代碼中的?makePointByXY?方法與?makePointByRA?方法也稱為工廠方法,如果把工廠方法放到一個其他的類中,這個類就叫做“工廠類”,總的來說,通過靜態(tài)方法封裝?new?操作,在方法內部設定不同的屬性來完成對象的初始化,構造對象的過程,就是工廠模式。

(5)?handler(拒絕策略)

? ? ? ? 第七個參數(shù):RejectedExecutionHandler?handler?這個參數(shù)可以算是最重要的一個參數(shù),在前面介紹的第五個參數(shù):BlockingQueue了<Runnable> workQueue?這是線程池中的一個阻塞隊列,用來存儲當前線程池要執(zhí)行的任務都有哪些,它能夠容納的元素是有上限的,此時當這個阻塞隊列中的任務已經排滿了,還有新的任務要往這個阻塞隊列中添加,線程池該怎么辦?這就需要我們的第七個參數(shù):RejectedExecutionHandler?handler?來指明一個拒絕策略,如下圖所示:

? ? ? ? 上圖中的這四個類也就代表了四種拒絕策略,它們所對應的拒絕策略如下表所示:

拒絕策略

ThreadPoolExecutor.AbortPolicy

繼續(xù)添加任務,直接拋出異常。
ThreadPoolExecutor.CallerRunsPolicy新的任務由添加任務的線程負責執(zhí)行。
ThreadPoolExecutor.DiscardOldestPolicy丟棄最老的任務,添加新的任務。
ThreadPoolExecutor.DiscardPolicy丟棄最新的任務。

3.使用標準庫中線程池

? ? ? ? 上面介紹了?ThreadPoolExecutor?類的構造方法及構造方法中的參數(shù),可以看出來?ThreadPoolExecutor?類本身用起來比較復雜,因此在標準庫中還提供了另一個版本的線程池,也就是把?ThreadPoolExecutor?類給封裝了一下,這個線程池就是?Executors?工廠類,通過這個類來創(chuàng)建出的不同線程池對象,Executors?類在內部把?ThreadPoolExecutor?創(chuàng)建好了,并且設置了不同的參數(shù),下面就使用?Executors?演示一下標準庫中線程池的效果吧。

? ? ? ? 如下圖所示,在?Executors?中內置了很多版本的線程池,這里我們使用固定數(shù)目的線程池來簡單演示一下線程池的效果即可。

? ? ? ? 下面使用線程池的具體代碼及運行結果如下所示:?

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TestDemo7 {public static void main(String[] args) {// ExecutorService 提供了一種管理和控制異步任務執(zhí)行的方式ExecutorService service = Executors.newFixedThreadPool(4);// 使用 submit 方法把任務添加到線程池中service.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello");}});}
}

? ? ? ? ?介紹完這兩個標準庫中的線程池,可以明確一點,當我們只是想簡單用一下線程池,就可以使用?Executors ,當我們希望高度定制化一個線程池,就可以使用?ThreadPoolExecutor。

三、實現(xiàn)線程池

? ? ? ? 在前面介紹了標準庫中的線程池及演示了使用的效果,下面我就來寫代碼實現(xiàn)一個簡單的線程池,這里我就直接寫一個固定線程數(shù)目的線程池,下面是這個簡單線程池中包含的內容:

  1. 提供構造方法,指定創(chuàng)建多少個線程;
  2. 在構造方法中,把這些線程都創(chuàng)建好;
  3. 創(chuàng)建一個阻塞隊列,能夠持有要執(zhí)行的任務;
  4. 提供?submit?方法,可以添加新的任務。

? ? ? ? 那么下面我就直接上代碼了,關于這個簡單線程池實現(xiàn)的細節(jié)我會在代碼中以注釋的方式進行介紹,線程池實現(xiàn)的代碼及運行結果如下所示:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;class MyThreadPoolExecutor {// 創(chuàng)建阻塞隊列,用來接收任務,這里設置最多容納任務量為 100private BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(100);// 創(chuàng)建線程鏈表,把創(chuàng)建的每個線程都用線程鏈表組織起來private List<Thread> threadList = new ArrayList<>();// 構造方法,指定線程池中固定的線程數(shù),并且將線程都創(chuàng)建好public MyThreadPoolExecutor(int num) {for (int i = 0; i < num; i++) {Thread t = new Thread(()->{while (true) {// 利用 runnable 來接收阻塞隊列中的任務Runnable runnable = null;try {// 獲取任務runnable = blockingQueue.take();} catch (InterruptedException e) {throw new RuntimeException(e);}// 執(zhí)行任務runnable.run();}});// 啟動線程t.start();// 將線程加入到線程鏈表中threadList.add(t);}}// 方法 sumbit 用來向阻塞隊列中添加新的任務public void sumbit(Runnable runnable) throws InterruptedException {blockingQueue.put(runnable);}
}public class ThreadDemo8 {public static void main(String[] args) throws InterruptedException {// 創(chuàng)建線程池,指定線程數(shù)目為 4MyThreadPoolExecutor executor = new MyThreadPoolExecutor(4);// 循環(huán) 100 次,向線程池中添加 100 個任務for (int i = 0; i < 100; i++) {int n = i;executor.sumbit(new Runnable() {@Overridepublic void run() {// 任務的內容System.out.println("執(zhí)行任務:->" + n + ",執(zhí)行的線程是:->" + Thread.currentThread().getName());}});}}
}

? ? ? ? 如上圖的運行結果可以看出,多個線程之間的執(zhí)行順序是不確定的,某個線程獲取到了某個任務,但并非是立即執(zhí)行,在這個過程中很有可能另一個線程就插到前面了,這里的這些線程彼此之間都是等價的。

·結尾

? ? ? ? 文章到這里就要結束了,回顧本篇文章,我介紹了什么是線程池,標準庫中線程池還有實現(xiàn)了一個簡單的線程池,其中還是要多理解一下標準庫中線程池構造方法每個參數(shù)的意思,及理解拒絕策略的含義,這可以讓我們對?ThreadPoolExecutor?類的使用更加清晰,后面實現(xiàn)的線程池也就可以看出線程池基本的工作原理,那就是不斷利用這 4 個線程來執(zhí)行任務,這樣就省去創(chuàng)建和銷毀線程的開銷,那么如果你感覺本篇文章對你有所幫助,還是希望能收到你的三連鼓勵,如果對文章的內容有所疑問歡迎在評論區(qū)進行討論,我們下一篇文章再見吧~~~

http://m.aloenet.com.cn/news/41899.html

相關文章:

  • 貿易網(wǎng)站有哪些杭州網(wǎng)站建設方案優(yōu)化
  • 完美世界培訓機構seo研究中心vip課程
  • 京東商城網(wǎng)官網(wǎng)seo工資待遇 seo工資多少
  • 網(wǎng)站建設要如何選擇成都百度推廣電話
  • 做寵物網(wǎng)站心得谷歌seo怎么優(yōu)化
  • 域名注冊 網(wǎng)站建設 好做嗎網(wǎng)站頁面分析
  • 有什么網(wǎng)站可以做微信吳江網(wǎng)站制作
  • 長春做網(wǎng)站網(wǎng)站搜狐財經峰會
  • 重慶經典論壇新聞評論windows優(yōu)化大師值得買嗎
  • 做的網(wǎng)站響應速度慢免費二級域名注冊網(wǎng)站有哪些
  • 建新建設集團有限公司網(wǎng)站萬物識別掃一掃
  • 寫微信小程序需要什么軟件怎么優(yōu)化一個網(wǎng)站關鍵詞
  • win服務器做網(wǎng)站今日重大新聞頭條財經
  • 海南哪家公司做網(wǎng)站信息流廣告有哪些投放平臺
  • 廣東省建設工程金匠獎公布網(wǎng)站優(yōu)化網(wǎng)址
  • 嘉興微信網(wǎng)站百度極簡網(wǎng)址
  • 四川鴻業(yè)建設集團網(wǎng)站廣告關鍵詞
  • 金融集團網(wǎng)站模板最新新聞
  • 網(wǎng)站跟app的區(qū)別是什么公司網(wǎng)站設計需要多少錢
  • 簡單的企業(yè)網(wǎng)站模板中國職業(yè)培訓在線官方網(wǎng)站
  • 做跨境的網(wǎng)站有哪些內容關鍵詞指數(shù)查詢工具
  • 咋建網(wǎng)站圖片識別 在線百度識圖
  • 叫別人做網(wǎng)站需要注意什么品牌策劃方案模板
  • 收企業(yè)做網(wǎng)站備案西安網(wǎng)約車
  • 在哪個網(wǎng)站做淘寶水印資源
  • 承德網(wǎng)站制作青島優(yōu)化網(wǎng)站關鍵詞
  • 網(wǎng)站開發(fā)費用清單淘寶指數(shù)官網(wǎng)
  • 頁面模板怎么修改鄭州seo排名優(yōu)化公司
  • 威海哪家網(wǎng)站做的好北京seo招聘信息
  • 襄陽哪里有做網(wǎng)站的手機app開發(fā)