阿里P7告訴你什么是java并發(fā)包架专、線程池同窘、鎖

并發(fā)包

java.util.concurrent從jdk1.5開(kāi)始新加入的一個(gè)包,致力于解決并發(fā)編程的線程安全問(wèn)題部脚,使用戶能夠更為快捷方便的編寫多線程情況下的并發(fā)程序想邦。

同步容器

同步容器只有包括Vector和HashTable,相比其他容器類只是多用了Synchronize的技術(shù)

Vector與ArrayList區(qū)別

1.ArrayList是最常用的List實(shí)現(xiàn)類,內(nèi)部是通過(guò)數(shù)組實(shí)現(xiàn)的委刘,它允許對(duì)元素進(jìn)行快速隨機(jī)訪問(wèn)丧没。數(shù)組的缺點(diǎn)是每個(gè)元素之間不能有間隔,當(dāng)數(shù)組大小不滿足時(shí)需要增加存儲(chǔ)能力锡移,就要講已經(jīng)有數(shù)組的數(shù)據(jù)復(fù)制到新的存儲(chǔ)空間中呕童。當(dāng)從ArrayList的中間位置插入或者刪除元素時(shí),需要對(duì)數(shù)組進(jìn)行復(fù)制淆珊、移動(dòng)夺饲、代價(jià)比較高。因此套蒂,它適合隨機(jī)查找和遍歷钞支,不適合插入和刪除。

2.Vector與ArrayList一樣操刀,也是通過(guò)數(shù)組實(shí)現(xiàn)的烁挟,不同的是它支持線程的同步,即某一時(shí)刻只有一個(gè)線程能夠?qū)慥ector骨坑,避免多線程同時(shí)寫而引起的不一致性撼嗓,但實(shí)現(xiàn)同步需要很高的花費(fèi),因此欢唾,訪問(wèn)它比訪問(wèn)ArrayList慢

注意: Vector線程安全且警、ArrayList線程不安全

HasTable與HasMap區(qū)別

1.HashMap不是線程安全的?

HastMap是一個(gè)接口 是map接口的子接口,是將鍵映射到值的對(duì)象礁遣,其中鍵和值都是對(duì)象斑芜,并且不能包含重復(fù)鍵,但可以包含重復(fù)值祟霍。HashMap允許null key和null value杏头,而hashtable不允許。

2.HashTable是線程安全的一個(gè)Collection沸呐。

3.HashMap是Hashtable的輕量級(jí)實(shí)現(xiàn)(非線程安全的實(shí)現(xiàn))醇王,他們都完成了Map接口,主要區(qū)別在于HashMap允許空(null)鍵值(key),由于非線程安全崭添,效率上可能高于Hashtable寓娩。

HashMap允許將null作為一個(gè)entry的key或者value,而Hashtable不允許。

HashMap把Hashtable的contains方法去掉了棘伴,改成containsvalue和containsKey寞埠。

注意: HashTable線程安全,HashMap線程不安全排嫌。

synchronizedMap synchronizedList

Collections.synchronized*(m) 將線程不安全集合變?yōu)榫€程安全集合

Map m = Collections.synchronizedMap(new HashMap());??

List l = Collections.synchronizedList(new ArrayList());

ConcurrentHashMap

ConcurrentHashMap內(nèi)部使用段(Segment)來(lái)表示這些不同的部分畸裳,每個(gè)段其實(shí)就是一個(gè)小的HashTable,它們有自己的鎖。只要多個(gè)修改操作發(fā)生在不同的段上淳地,它們就可以并發(fā)進(jìn)行怖糊。把一個(gè)整體分成了16個(gè)段(Segment)也就是最高支持16個(gè)線程的并發(fā)修改操作。

這也是在重線程場(chǎng)景時(shí)減小鎖的粒度從而降低鎖競(jìng)爭(zhēng)的一種方案颇象。并且代碼中大多共享變量使用volatile關(guān)鍵字聲明伍伤,目的是第一時(shí)間獲取修改的內(nèi)容,性能非常好遣钳。

大家可以點(diǎn)擊加入群:【Java高級(jí)架構(gòu)進(jìn)階群】:854180697 里面有Java高級(jí)大牛直播講解知識(shí)點(diǎn) 走的就是高端路線扰魂,(如果你想跳槽換工作 但是技術(shù)又不夠 或者工作上遇到了瓶頸 ,我這里有一個(gè)JAVA的免費(fèi)直播課程 蕴茴,講的是高端的知識(shí)點(diǎn)基礎(chǔ)不好的誤入喲劝评,只要你有1-5年的開(kāi)發(fā)經(jīng)驗(yàn)可以加群找我要課堂鏈接 注意:是免費(fèi)的 沒(méi)有開(kāi)發(fā)經(jīng)驗(yàn)誤入哦)

并發(fā)容器

CountDownLatch

CountDownLatch是JAVA提供在java.util.concurrent包下的一個(gè)輔助類,可以把它看成是一個(gè)計(jì)數(shù)器倦淀,其內(nèi)部維護(hù)著一個(gè)count計(jì)數(shù)蒋畜,只不過(guò)對(duì)這個(gè)計(jì)數(shù)器的操作都是原子操作,同時(shí)只能有一個(gè)線程去操作這個(gè)計(jì)數(shù)器撞叽,CountDownLatch通過(guò)構(gòu)造函數(shù)傳入一個(gè)初始計(jì)數(shù)值姻成,調(diào)用者可以通過(guò)調(diào)用CounDownLatch對(duì)象的cutDown()方法,來(lái)使計(jì)數(shù)減1愿棋;如果調(diào)用對(duì)象上的await()方法科展,那么調(diào)用者就會(huì)一直阻塞在這里,直到別人通過(guò)cutDown方法糠雨,將計(jì)數(shù)減到0才睹,才可以繼續(xù)執(zhí)行。

public class Test002 {??public static void main(String[] args) throws InterruptedException {????System.out.println("等待子線程執(zhí)行完畢...");????CountDownLatch countDownLatch = new CountDownLatch(2);????new Thread(new Runnable() {??????@Override??????public void run() {????????System.out.println("子線程," +Thread.currentThread().getName() + "開(kāi)始執(zhí)行...");????????countDownLatch.countDown();// 每次減去1????????System.out.println("子線程," + Thread.currentThread().getName() + "結(jié)束執(zhí)行...");??????}????}).start();????new Thread(new Runnable() {??????@Override??????public void run() {????????System.out.println("子線程," + Thread.currentThread().getName() + "開(kāi)始執(zhí)行...");????????countDownLatch.countDown();????????System.out.println("子線程," + Thread.currentThread().getName() + "結(jié)束執(zhí)行...");????????}??????}).start();??????countDownLatch.await();// 調(diào)用當(dāng)前方法主線程阻塞?countDown結(jié)果為0, 阻塞變?yōu)檫\(yùn)行狀態(tài)??????System.out.println("兩個(gè)子線程執(zhí)行完畢....");??????System.out.println("繼續(xù)主線程執(zhí)行..");????}}

CyclicBarrier

一個(gè)同步輔助類甘邀,它允許一組線程互相等待描函,直到到達(dá)某個(gè)公共屏障點(diǎn) (common barrier point)泥畅。在涉及一組固定大小的線程的程序中何鸡,這些線程必須不時(shí)地互相等待骑歹,此時(shí) CyclicBarrier 很有用叁温。因?yàn)樵?barrier 在釋放等待線程后可以重用特铝,所以稱它為循環(huán) 的 barrier慨仿。

使用場(chǎng)景

需要所有的子任務(wù)都完成時(shí)所坯,才執(zhí)行主任務(wù),這個(gè)時(shí)候就可以選擇使用CyclicBarrier锋八。

public class CyclicBarrierTest {??public static void main(String[] args) throws IOException, InterruptedException {????//如果將參數(shù)改為4浙于,但是下面只加入了3個(gè)選手,這永遠(yuǎn)等待下去????//Waits until all parties have invoked await on this barrier.?????CyclicBarrier barrier = new CyclicBarrier(3);????ExecutorService executor = Executors.newFixedThreadPool(3);????executor.submit(new Thread(new Runner(barrier, "1號(hào)選手")));????executor.submit(new Thread(new Runner(barrier, "2號(hào)選手")));????executor.submit(new Thread(new Runner(barrier, "3號(hào)選手")));????executor.shutdown();??}}class Runner implements Runnable {??// 一個(gè)同步輔助類挟纱,它允許一組線程互相等待羞酗,直到到達(dá)某個(gè)公共屏障點(diǎn) (common barrier point)??private CyclicBarrier barrier;??private String name;??public Runner(CyclicBarrier barrier, String name) {????super();????this.barrier = barrier;????this.name = name;??}??@Override??public void run() {????try {??????Thread.sleep(1000 * (new Random()).nextInt(8));??????System.out.println(name + " 準(zhǔn)備好了...");??????// barrier的await方法,在所有參與者都已經(jīng)在此 barrier 上調(diào)用 await 方法之前紊服,將一直等待檀轨。??????barrier.await();????} catch (InterruptedException e) {??????e.printStackTrace();????} catch (BrokenBarrierException e) {??????e.printStackTrace();????}????System.out.println(name + " 起跑!");??}}

Semaphore

Semaphore是計(jì)數(shù)信號(hào)量欺嗤。Semaphore管理一系列許可證参萄。每個(gè)acquire方法阻塞,直到有一個(gè)許可證可以獲得然后拿走一個(gè)許可證煎饼;每個(gè)release方法增加一個(gè)許可證讹挎,這可能會(huì)釋放一個(gè)阻塞的acquire方法。然而吆玖,其實(shí)并沒(méi)有實(shí)際的許可證這個(gè)對(duì)象筒溃,Semaphore只是維持了一個(gè)可獲得許可證的數(shù)量。?

Semaphore經(jīng)常用于限制獲取某種資源的線程數(shù)量

需求: 一個(gè)廁所只有3個(gè)坑位沾乘,但是有10個(gè)人來(lái)上廁所怜奖,那怎么辦?假設(shè)10個(gè)人的編號(hào)分別為1-10意鲸,并且1號(hào)先到廁所烦周,10號(hào)最后到廁所。那么1-3號(hào)來(lái)的時(shí)候必然有可用坑位怎顾,順利如廁读慎,4號(hào)來(lái)的時(shí)候需要看看前面3人是否有人出來(lái)了,如果有人出來(lái)槐雾,進(jìn)去夭委,否則等待。同樣的道理募强,4-10號(hào)也需要等待正在上廁所的人出來(lái)后才能進(jìn)去株灸,并且誰(shuí)先進(jìn)去這得看等待的人是否有素質(zhì),是否能遵守先來(lái)先上的規(guī)則擎值。

class Parent implements Runnable {??private String name;??private Semaphore wc;??public Parent(String name,Semaphore wc){????this.name=name;????this.wc=wc;??}??@Override??public void run() {????try {??????// 剩下的資源(剩下的茅坑)??????int availablePermits = wc.availablePermits();??????if (availablePermits > 0) {????????System.out.println(name+"天助我也,終于有茅坑了...");??????} else {????????System.out.println(name+"怎么沒(méi)有茅坑了...");??????}??????//申請(qǐng)茅坑 如果資源達(dá)到3次慌烧,就等待??????wc.acquire();??????System.out.println(name+"終于輪我上廁所了..爽啊");????????Thread.sleep(new Random().nextInt(1000)); // 模擬上廁所時(shí)間。??????System.out.println(name+"廁所上完了...");??????wc.release();????} catch (Exception e) {????}??}}public class TestSemaphore02 {??public static void main(String[] args) {????Semaphore semaphore = new Semaphore(3);????for (int i = 1; i <=10; i++) {???????Parent parent = new Parent("第"+i+"個(gè)人,",semaphore);???????new Thread(parent).start();????}??}}

并發(fā)隊(duì)列

ConcurrentLinkedQueue

ConcurrentLinkedQueue : 是一個(gè)適用于高并發(fā)場(chǎng)景下的隊(duì)列鸠儿,通過(guò)無(wú)鎖的方式屹蚊,實(shí)現(xiàn)了高并發(fā)狀態(tài)下的高性能厕氨,通常ConcurrentLinkedQueue性能好于BlockingQueue.它是一個(gè)基于鏈接節(jié)點(diǎn)的無(wú)界線程安全隊(duì)列。該隊(duì)列的元素遵循先進(jìn)先出的原則汹粤。頭是最先加入的命斧,尾是最近加入的,該隊(duì)列不允許null元素嘱兼。

add 和offer() 都是加入元素的方法(在ConcurrentLinkedQueue中這倆個(gè)方法沒(méi)有任何區(qū)別) poll() 和peek() 都是取頭元素節(jié)點(diǎn)国葬,區(qū)別在于前者會(huì)刪除元素,后者不會(huì)芹壕。

public class ConcurrentLinkedQueueTest {

??private static ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();

??private static int count = 2; // 線程個(gè)數(shù)

??//CountDownLatch汇四,一個(gè)同步輔助類,在完成一組正在其他線程中執(zhí)行的操作之前哪雕,它允許一個(gè)或多個(gè)線程一直等待船殉。

??private static CountDownLatch latch = new CountDownLatch(count);??public static void main(String[] args) throws InterruptedException {????long timeStart = System.currentTimeMillis();????ExecutorService es = Executors.newFixedThreadPool(4);????ConcurrentLinkedQueueTest.offer();????for (int i = 0; i < count; i++) {??????es.submit(new Poll());????}????latch.await(); //使得主線程(main)阻塞直到latch.countDown()為零才繼續(xù)執(zhí)行????System.out.println("cost time " + (System.currentTimeMillis() - timeStart) + "ms");????es.shutdown();??}??/**???* 生產(chǎn)???*/??public static void offer() {????for (int i = 0; i < 100000; i++) {??????queue.offer(i);????}??}??static class Poll implements Runnable {????public void run() {??????// while (queue.size()>0) {??????while (!queue.isEmpty()) {????????System.out.println(queue.poll());??????}??????latch.countDown();????}??}}

BlockingQueue

阻塞隊(duì)列(BlockingQueue)是一個(gè)支持兩個(gè)附加操作的隊(duì)列。這兩個(gè)附加的操作是:

在隊(duì)列為空時(shí)斯嚎,獲取元素的線程會(huì)等待隊(duì)列變?yōu)榉强铡?/p>

當(dāng)隊(duì)列滿時(shí)利虫,存儲(chǔ)元素的線程會(huì)等待隊(duì)列可用。?

阻塞隊(duì)列常用于生產(chǎn)者和消費(fèi)者的場(chǎng)景堡僻,生產(chǎn)者是往隊(duì)列里添加元素的線程糠惫,消費(fèi)者是從隊(duì)列里拿元素的線程。阻塞隊(duì)列就是生產(chǎn)者存放元素的容器钉疫,而消費(fèi)者也只從容器里拿元素

ArrayBlockingQueue

ArrayBlockingQueue是一個(gè)有邊界的阻塞隊(duì)列硼讽,它的內(nèi)部實(shí)現(xiàn)是一個(gè)數(shù)組。有邊界的意思是它的容量是有限的牲阁,我們必須在其初始化的時(shí)候指定它的容量大小固阁,容量大小一旦指定就不可改變。

ArrayBlockingQueue是以先進(jìn)先出的方式存儲(chǔ)數(shù)據(jù)城菊,最新插入的對(duì)象是尾部备燃,最新移出的對(duì)象是頭部。

LinkedBlockingQueue

LinkedBlockingQueue阻塞隊(duì)列大小的配置是可選的凌唬,如果我們初始化時(shí)指定一個(gè)大小并齐,它就是有邊界的,如果不指定客税,它就是無(wú)邊界的况褪。說(shuō)是無(wú)邊界,其實(shí)是采用了默認(rèn)大小為Integer.MAX_VALUE的容量 更耻。它的內(nèi)部實(shí)現(xiàn)是一個(gè)鏈表

SynchronousQueue

SynchronousQueue隊(duì)列內(nèi)部?jī)H允許容納一個(gè)元素测垛。當(dāng)一個(gè)線程插入一個(gè)元素后會(huì)被阻塞,除非這個(gè)元素被另一個(gè)線程消費(fèi)

public class BlockingQueueTest2 {??/**???*????* 定義裝蘋果的籃子???*????*/??public class Basket {????// 籃子秧均,能夠容納3個(gè)蘋果????BlockingQueue basket = new LinkedBlockingQueue(3);????// 生產(chǎn)蘋果赐纱,放入籃子????public void produce() throws InterruptedException {??????// put方法放入一個(gè)蘋果脊奋,若basket滿了,等到basket有位置??????basket.put("An apple");????}????// 消費(fèi)蘋果疙描,從籃子中取走????public String consume() throws InterruptedException {??????// take方法取出一個(gè)蘋果,若basket為空讶隐,等到basket有蘋果為止(獲取并移除此隊(duì)列的頭部)??????return basket.take();????}??}??// 定義蘋果生產(chǎn)者??class Producer implements Runnable {????private String instance;????private Basket basket;????public Producer(String instance, Basket basket) {??????this.instance = instance;??????this.basket = basket;????}????public void run() {??????try {????????while (true) {??????????// 生產(chǎn)蘋果??????????System.out.println("生產(chǎn)者準(zhǔn)備生產(chǎn)蘋果:" + instance);??????????basket.produce();??????????System.out.println("!生產(chǎn)者生產(chǎn)蘋果完畢:" + instance);??????????// 休眠300ms??????????Thread.sleep(300);????????}??????} catch (InterruptedException ex) {????????System.out.println("Producer Interrupted");??????}????}??}??// 定義蘋果消費(fèi)者??class Consumer implements Runnable {????private String instance;????private Basket basket;????public Consumer(String instance, Basket basket) {??????this.instance = instance;??????this.basket = basket;????}????public void run() {??????try {????????while (true) {??????????// 消費(fèi)蘋果??????????System.out.println("消費(fèi)者準(zhǔn)備消費(fèi)蘋果:" + instance);??????????System.out.println(basket.consume());??????????System.out.println("!消費(fèi)者消費(fèi)蘋果完畢:" + instance);??????????// 休眠1000ms??????????Thread.sleep(1000);????????}??????} catch (InterruptedException ex) {????????System.out.println("Consumer Interrupted");??????}????}??}??public static void main(String[] args) {????BlockingQueueTest2 test = new BlockingQueueTest2();????// 建立一個(gè)裝蘋果的籃子????Basket basket = test.new Basket();????ExecutorService service = Executors.newCachedThreadPool();????Producer producer = test.new Producer("生產(chǎn)者001", basket);????Producer producer2 = test.new Producer("生產(chǎn)者002", basket);????Consumer consumer = test.new Consumer("消費(fèi)者001", basket);????service.submit(producer);????service.submit(producer2);????service.submit(consumer);????// 程序運(yùn)行5s后起胰,所有任務(wù)停止//????try {//??????Thread.sleep(1000 * 5);//????} catch (InterruptedException e) {//??????e.printStackTrace();//????}//????service.shutdownNow();??}}

PriorityBlockingQueue

優(yōu)先級(jí)阻塞隊(duì)列,該實(shí)現(xiàn)類需要自己實(shí)現(xiàn)一個(gè)繼承了 Comparator 接口的類, 在插入資源時(shí)會(huì)按照自定義的排序規(guī)則來(lái)對(duì)資源數(shù)組進(jìn)行排序巫延。 其中值大的排在數(shù)組后面 效五,取值時(shí)從數(shù)組頭開(kāi)始取

public class TestQueue{??static Logger logger = LogManager.getLogger();??static Random random = new Random(47);??public static void main(String args[]) throws InterruptedException??{????PriorityBlockingQueue queue = new PriorityBlockingQueue();????ExecutorService executor = Executors.newCachedThreadPool();????executor.execute(new Runnable()????{??????public void run()??????{????????int i = 0;????????while (true)????????{??????????queue.put(new PriorityEntity(random.nextInt(10), i++));??????????try??????????{????????????TimeUnit.MILLISECONDS.sleep(random.nextInt(1000));??????????}??????????catch (InterruptedException e)??????????{????????????logger.error(e);??????????}????????}??????}????});????executor.execute(new Runnable()????{??????public void run()??????{????????while (true)????????{??????????try??????????{????????????System.out.println("take-- " + queue.take() + " left:-- [" + queue.toString() + "]");????????????try????????????{??????????????TimeUnit.MILLISECONDS.sleep(random.nextInt(3000));????????????}????????????catch (InterruptedException e)????????????{??????????????logger.error(e);????????????}??????????}??????????catch (InterruptedException e)??????????{????????????logger.error(e);??????????}????????}??????}????});????try????{??????TimeUnit.SECONDS.sleep(5);????}????catch (InterruptedException e)????{??????logger.error(e);????}??}??static class PriorityEntity implements Comparable??{????private static int count = 0;????private int id = count++;????private int priority;????private int index = 0;????public PriorityEntity(int _priority, int _index)????{??????System.out.println("_priority : " + _priority);??????this.priority = _priority;??????this.index = _index;????}????public String toString()????{??????return id + "# [index=" + index + " priority=" + priority + "]";????}????//數(shù)字小,優(yōu)先級(jí)高????public int compareTo(PriorityEntity o)????{??????return this.priority > o.priority ? 1 : this.priority < o.priority ? -1 : 0;????}??}}

線程池

開(kāi)發(fā)過(guò)程中,合理地使用線程池可以帶來(lái)3個(gè)好處:

降低資源消耗:通過(guò)重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗炉峰。

提高響應(yīng)速度:當(dāng)任務(wù)到達(dá)時(shí)畏妖,任務(wù)可以不需要等到線程創(chuàng)建就能立即執(zhí)行。

提高線程的可管理性:線程是稀缺資源疼阔,如果無(wú)限制地創(chuàng)建戒劫,不僅會(huì)消耗系統(tǒng)資源,還會(huì)降低系統(tǒng)的穩(wěn)定性婆廊,使用線程池可以進(jìn)行統(tǒng)一分配迅细、調(diào)優(yōu)和監(jiān)控。

線程池作用

線程池作用就是限制系統(tǒng)中執(zhí)行線程的數(shù)量淘邻。

根據(jù)系統(tǒng)的環(huán)境情況茵典,可以自動(dòng)或手動(dòng)設(shè)置線程數(shù)量,達(dá)到運(yùn)行的最佳效果宾舅;少了浪費(fèi)了系統(tǒng)資源统阿,多了造成系統(tǒng)擁擠效率不高。用線程池控制線程數(shù)量筹我,其他線程排隊(duì)等候扶平。一個(gè)任務(wù)執(zhí)行完畢,再?gòu)年?duì)列的中取最前面的任務(wù)開(kāi)始執(zhí)行崎溃。若隊(duì)列中沒(méi)有等待進(jìn)程蜻直,線程池的這一資源處于等待。當(dāng)一個(gè)新任務(wù)需要運(yùn)行時(shí)袁串,如果線程池中有等待的工作線程概而,就可以開(kāi)始運(yùn)行了;否則進(jìn)入等待隊(duì)列囱修。

線程池的分類

newCachedThreadPool

創(chuàng)建一個(gè)可緩存線程池赎瑰,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程破镰,若無(wú)可回收餐曼,則新建線程

public static ExecutorService newCachedThreadPool() {????return new ThreadPoolExecutor(0, Integer.MAX_VALUE,???????????????????60L, TimeUnit.SECONDS,???????????????????new SynchronousQueue());??}public class ThreadPoolExecutorTest {????public static void main(String[] args) {??????ExecutorService cachedThreadPool = Executors.newCachedThreadPool();???????for (int i = 0; i < 10; i++) {??????????final int index = i;??????????try {??????????Thread.sleep(index * 1000);??????????} catch (InterruptedException e) {??????????e.printStackTrace();??????????}??????????cachedThreadPool.execute(new Runnable() {??????????public void run() {?????????????System.out.println(index);??????????}????????});???????}?????}??}??

線程池為無(wú)限大压储,當(dāng)執(zhí)行第二個(gè)任務(wù)時(shí)第一個(gè)任務(wù)已經(jīng)完成,會(huì)復(fù)用執(zhí)行第一個(gè)任務(wù)的線程源譬,而不用每次新建線程

newFixedThreadPool

創(chuàng)建一個(gè)定長(zhǎng)線程池集惋,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待踩娘。

public static ExecutorService newFixedThreadPool(int nThreads) {????return new ThreadPoolExecutor(nThreads, nThreads,???????????????????0L, TimeUnit.MILLISECONDS,???????????????????new LinkedBlockingQueue());}public class ThreadPoolExecutorTest {????public static void main(String[] args) {??????ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);??????for (int i = 0; i < 10; i++) {????????final int index = i;????????fixedThreadPool.execute(new Runnable() {??????????public void run() {????????????try {??????????????System.out.println(index);??????????????Thread.sleep(2000);????????????} catch (InterruptedException e) {??????????????e.printStackTrace();????????????}??????????}????????});??????}????}??}?

因?yàn)榫€程池大小為3刮刑,每個(gè)任務(wù)輸出index后sleep 2秒,所以每?jī)擅氪蛴?個(gè)數(shù)字养渴。定長(zhǎng)線程池的大小最好根據(jù)系統(tǒng)資源進(jìn)行設(shè)置雷绢。如Runtime.getRuntime().availableProcessors()

newScheduledThreadPool

創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)及周期性任務(wù)執(zhí)行理卑。

public ScheduledThreadPoolExecutor(int corePoolSize) {????super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,???????new DelayedWorkQueue());??}public class ThreadPoolExecutorTest {????public static void main(String[] args) {??????ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);??????scheduledThreadPool.schedule(new Runnable() {????????public void run() {??????????System.out.println("delay 3 seconds");????????}??????}, 3, TimeUnit.SECONDS);????}??}??

表示延遲3秒執(zhí)行

public class ThreadPoolExecutorTest {????public static void main(String[] args) {??????ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);??????scheduledThreadPool.scheduleAtFixedRate(new Runnable() {????????public void run() {??????????System.out.println("delay 1 seconds, and excute every 3 seconds");????????}??????}, 1, 3, TimeUnit.SECONDS);????}??}??

表示延遲1秒后每3秒執(zhí)行一次

newSingleThreadExecutor

創(chuàng)建一個(gè)單線程化的線程池翘紊,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行藐唠。

public static ExecutorService newSingleThreadExecutor() {????return new FinalizableDelegatedExecutorService??????(new ThreadPoolExecutor(1, 1,??????????????????0L, TimeUnit.MILLISECONDS,??????????????????new LinkedBlockingQueue()));??}

阿里發(fā)布的 Java開(kāi)發(fā)手冊(cè)中強(qiáng)制線程池不允許使用 Executors 去創(chuàng)建帆疟,而是通過(guò) ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運(yùn)行規(guī)則中捆,規(guī)避資源耗盡的風(fēng)險(xiǎn)

ThreadPoolExecutor??public ThreadPoolExecutor(int corePoolSize,???????????????

int maximumPoolSize,??????????????

?long keepAliveTime,??????????????

?TimeUnit unit,???????????????

BlockingQueue workQueue,??????????????

ThreadFactory threadFactory,???????????????

RejectedExecutionHandler handler)?

corePoolSize - 線程池核心池的大小鸯匹。

maximumPoolSize - 線程池的最大線程數(shù)。

keepAliveTime - 當(dāng)線程數(shù)大于核心時(shí)泄伪,此為終止前多余的空閑線程等待新任務(wù)的最長(zhǎng)時(shí)間殴蓬。

unit - keepAliveTime 的時(shí)間單位。

workQueue - 用來(lái)儲(chǔ)存等待執(zhí)行任務(wù)的隊(duì)列蟋滴。

threadFactory - 線程工廠染厅。

handler - 拒絕策略。

線程優(yōu)先級(jí):

corePoolSize > workQueue > maximumPoolSize>handler(拒絕)

拒絕策略:

CallerRunsPolicy :這個(gè)策略重試添加當(dāng)前的任務(wù)津函,他會(huì)自動(dòng)重復(fù)調(diào)用 execute() 方法肖粮,直到成功。

AbortPolicy :對(duì)拒絕任務(wù)拋棄處理尔苦,并且拋出異常涩馆。(默認(rèn)使用的)

DiscardPolicy :對(duì)拒絕任務(wù)直接無(wú)聲拋棄,沒(méi)有異常信息允坚。

DiscardOldestPolicy :對(duì)拒絕任務(wù)不拋棄魂那,而是拋棄隊(duì)列里面等待最久的一個(gè)線程,然后把拒絕任務(wù)加到隊(duì)列稠项。

合理配置線程池

要想合理的配置線程池涯雅,就必須首先分析任務(wù)特性,可以從以下幾個(gè)角度來(lái)進(jìn)行分析:

任務(wù)的性質(zhì):CPU密集型任務(wù)展运,IO密集型任務(wù)和混合型任務(wù)活逆。

任務(wù)的優(yōu)先級(jí):高精刷,中和低。

任務(wù)的執(zhí)行時(shí)間:長(zhǎng)蔗候,中和短怒允。

任務(wù)的依賴性:是否依賴其他系統(tǒng)資源,如數(shù)據(jù)庫(kù)連接琴庵。

任務(wù)性質(zhì)不同的任務(wù)可以用不同規(guī)模的線程池分開(kāi)處理误算。CPU密集型任務(wù)配置盡可能少的線程數(shù)量,如配置Ncpu+1個(gè)線程的線程池迷殿。IO密集型任務(wù)則由于需要等待IO操作,線程并不是一直在執(zhí)行任務(wù)咖杂,則配置盡可能多的線程庆寺,如2*Ncpu∷咦郑混合型的任務(wù)懦尝,如果可以拆分,則將其拆分成一個(gè)CPU密集型任務(wù)和一個(gè)IO密集型任務(wù)壤圃,只要這兩個(gè)任務(wù)執(zhí)行的時(shí)間相差不是太大陵霉,那么分解后執(zhí)行的吞吐率要高于串行執(zhí)行的吞吐率,如果這兩個(gè)任務(wù)執(zhí)行時(shí)間相差太大伍绳,則沒(méi)必要進(jìn)行分解踊挠。我們可以通過(guò)Runtime.getRuntime().availableProcessors()方法獲得當(dāng)前設(shè)備的CPU個(gè)數(shù)。

優(yōu)先級(jí)不同的任務(wù)可以使用優(yōu)先級(jí)隊(duì)列PriorityBlockingQueue來(lái)處理冲杀。它可以讓優(yōu)先級(jí)高的任務(wù)先得到執(zhí)行效床,需要注意的是如果一直有優(yōu)先級(jí)高的任務(wù)提交到隊(duì)列里,那么優(yōu)先級(jí)低的任務(wù)可能永遠(yuǎn)不能執(zhí)行权谁。

執(zhí)行時(shí)間不同的任務(wù)可以交給不同規(guī)模的線程池來(lái)處理剩檀,或者也可以使用優(yōu)先級(jí)隊(duì)列,讓執(zhí)行時(shí)間短的任務(wù)先執(zhí)行旺芽。

依賴數(shù)據(jù)庫(kù)連接池的任務(wù)沪猴,因?yàn)榫€程提交SQL后需要等待數(shù)據(jù)庫(kù)返回結(jié)果,如果等待的時(shí)間越長(zhǎng)CPU空閑時(shí)間就越長(zhǎng)采章,那么線程數(shù)應(yīng)該設(shè)置越大运嗜,這樣才能更好的利用CPU。

CPU密集型時(shí)共缕,任務(wù)可以少配置線程數(shù)洗出,大概和機(jī)器的cpu核數(shù)相當(dāng),這樣可以使得每個(gè)線程都在執(zhí)行任務(wù) IO密集型時(shí)图谷,大部分線程都阻塞翩活,故需要多配置線程數(shù)阱洪,2*cpu核數(shù) 操作系統(tǒng)之名稱解釋: 某些進(jìn)程花費(fèi)了絕大多數(shù)時(shí)間在計(jì)算上,而其他則在等待I/O上花費(fèi)了大多是時(shí)間菠镇,前者稱為計(jì)算密集型(CPU密集型)computer-bound冗荸,后者稱為I/O密集型,I/O-bound利耍。

寫在最后:歡迎留言討論蚌本,加關(guān)注,持續(xù)更新0妗3贪!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末轴猎,一起剝皮案震驚了整個(gè)濱河市嵌莉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捻脖,老刑警劉巖锐峭,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異可婶,居然都是意外死亡沿癞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門矛渴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)椎扬,“玉大人,你說(shuō)我怎么就攤上這事曙旭〉两ⅲ” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵桂躏,是天一觀的道長(zhǎng)钻趋。 經(jīng)常有香客問(wèn)我,道長(zhǎng)剂习,這世上最難降的妖魔是什么蛮位? 我笑而不...
    開(kāi)封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮鳞绕,結(jié)果婚禮上失仁,老公的妹妹穿的比我還像新娘。我一直安慰自己们何,他們只是感情好萄焦,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般拂封。 火紅的嫁衣襯著肌膚如雪茬射。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天冒签,我揣著相機(jī)與錄音在抛,去河邊找鬼。 笑死萧恕,一個(gè)胖子當(dāng)著我的面吹牛刚梭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播票唆,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼朴读,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了走趋?” 一聲冷哼從身側(cè)響起磨德,我...
    開(kāi)封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吆视,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體酥宴,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡啦吧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拙寡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片授滓。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖肆糕,靈堂內(nèi)的尸體忽然破棺而出般堆,到底是詐尸還是另有隱情,我是刑警寧澤诚啃,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布淮摔,位于F島的核電站,受9級(jí)特大地震影響始赎,放射性物質(zhì)發(fā)生泄漏和橙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一造垛、第九天 我趴在偏房一處隱蔽的房頂上張望魔招。 院中可真熱鬧,春花似錦五辽、人聲如沸办斑。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)乡翅。三九已至鳞疲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間峦朗,已是汗流浹背建丧。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留波势,地道東北人翎朱。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像尺铣,于是被迫代替她去往敵國(guó)和親拴曲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容