wordpress 添加文章屬性武漢seo招聘
文章目錄
- 前言
- 1 線程池
- 1.1 線程池概述
- 1.1.1 線程池存在的意義
- 1.1.2 Executors默認(rèn)線程池
- 1.2 線程狀態(tài)介紹
- 1.2.1 線程狀態(tài)源碼
- 1.2.2 線程狀態(tài)含義
- 1.2.3 線程狀態(tài)轉(zhuǎn)換圖
- 2 原子性
- 2.1 volatile關(guān)鍵字
- 2.2 synchronized解決
- 2.3 原子性
- 2.4 AtomicInteger類
- 2.5 悲觀鎖和樂觀鎖
前言
“清琴濁酒鶯花日,雨笠煙蓑蟹稻鄉(xiāng)。棠蔭漸高身漸隱,已將心事托漁郎”???—張英 《贈(zèng)何匡山次梅村先生韻》
1 線程池
1.1 線程池概述
???????線程池也是可以看做成一個(gè)容器,在該容器中存儲(chǔ)很多個(gè)線程。
1.1.1 線程池存在的意義
???????系統(tǒng)創(chuàng)建一個(gè)線程的成本是比較高的,頻繁的創(chuàng)建和銷毀線程對(duì)系統(tǒng)的資源消耗非常大,所為了提高性能,我們就可以采用線程池。線程池在啟動(dòng)的時(shí),會(huì)創(chuàng)建大量空閑線程,當(dāng)我們向線程池提交任務(wù)的時(shí),線程池就會(huì)啟動(dòng)一個(gè)線程來執(zhí)行該任務(wù)。等待任務(wù)執(zhí)行完畢以后,線程并不會(huì)死亡,而是再次返回到線程池中稱為空閑狀態(tài)。等待下一次任務(wù)的執(zhí)行。
1.1.2 Executors默認(rèn)線程池
???????1.常見方法
// 1.創(chuàng)建一個(gè)默認(rèn)的線程池
static ExecutorService newCachedThreadPool()
// 2.創(chuàng)建一個(gè)指定最多線程數(shù)量的線程池
static newFixedThreadPool(int nThreads)
???????2.代碼實(shí)現(xiàn) :
package com.syh;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class MyThread {public static void main(String[] args) throws InterruptedException {// 1,創(chuàng)建一個(gè)默認(rèn)的線程池對(duì)象ExecutorService executorService = Executors.newCachedThreadPool();executorService.submit(()->{System.out.println(Thread.currentThread().getName() + "在執(zhí)行了");});// 2,等待2秒Thread.sleep(2000);executorService.submit(()->{System.out.println(Thread.currentThread().getName() + "在執(zhí)行了");});executorService.shutdown();}
}
1.2 線程狀態(tài)介紹
???????線程對(duì)象在不同的時(shí)期有不同的狀態(tài),一共有6種狀態(tài)
1.2.1 線程狀態(tài)源碼
public class Thread {public enum State {/* 新建 */NEW , /* 可運(yùn)行狀態(tài) */RUNNABLE , /* 阻塞狀態(tài) */BLOCKED , /* 無限等待狀態(tài) */WAITING , /* 計(jì)時(shí)等待 */TIMED_WAITING , /* 終止 */TERMINATED;}// 獲取當(dāng)前線程的狀態(tài)public State getState() {return jdk.internal.misc.VM.toThreadState(threadStatus);}}
1.2.2 線程狀態(tài)含義
線程狀態(tài) | 具體含義 |
---|---|
NEW | 一個(gè)尚未啟動(dòng)的線程的狀態(tài)。也稱之為初始狀態(tài)、開始狀態(tài)。線程剛被創(chuàng)建,但是并未啟動(dòng)。還沒調(diào)用start方法。MyThread t = new MyThread()只有線程象,沒有線程特征。 |
RUNNABLE | 當(dāng)我們調(diào)用線程對(duì)象的start方法,那么此時(shí)線程對(duì)象進(jìn)入了RUNNABLE狀態(tài)。那么此時(shí)才是真正的在JVM進(jìn)程中創(chuàng)建了一個(gè)線程,線程一經(jīng)啟動(dòng)并不是立即得到執(zhí)行,線程的運(yùn)行與否要聽令與CPU的調(diào)度,那么我們把這個(gè)中間狀態(tài)稱之為可執(zhí)行狀態(tài)(RUNNABLE)也就是說它具備執(zhí)行的資格,但是并沒有真正的執(zhí)行起來而是在等待CPU的度。 |
BLOCKED | 當(dāng)一個(gè)線程試圖獲取一個(gè)對(duì)象鎖,而該對(duì)象鎖被其他的線程持有,則該線程進(jìn)入Blocked狀態(tài);當(dāng)該線程持有鎖時(shí),該線程將變成Runnable狀態(tài)。 |
WAITING | 一個(gè)正在等待的線程的狀態(tài)。也稱之為等待狀態(tài)。造成線程等待的原因有兩種,分別是調(diào)用Object.wait()、join()方法。處于等待狀態(tài)的線程,正在等待其他線程去執(zhí)行一個(gè)特定的操作。例如:因?yàn)閣ait()而等待的線程正在等待另一個(gè)線程去調(diào)用notify()或notifyAll();一個(gè)因?yàn)閖oin()而等待的線程正在等待另一個(gè)線程結(jié)束。 |
TIMED_WAITING | 一個(gè)在限定時(shí)間內(nèi)等待的線程的狀態(tài)。也稱之為限時(shí)等待狀態(tài)。造成線程限時(shí)等待狀態(tài)的原因有三種,分別是:Thread.sleep(long),Object.wait(long)、join(long)。 |
TERMINATED | 一個(gè)完全運(yùn)行完成的線程的狀態(tài)。也稱之為終止?fàn)顟B(tài)、結(jié)束狀態(tài) |
1.2.3 線程狀態(tài)轉(zhuǎn)換圖
2 原子性
2.1 volatile關(guān)鍵字
1. 問題 :
當(dāng)A線程修改了共享數(shù)據(jù)時(shí),B線程沒有及時(shí)獲取到最新的值,如果還在使用原先的值,就會(huì)出現(xiàn)問題
-
堆內(nèi)存是唯一的,每一個(gè)線程都有自己的線程棧。
-
每一個(gè)線程在使用堆里面變量的時(shí)候,都會(huì)先拷貝一份到變量的副本中。
-
在線程中,每一次使用是從變量的副本中獲取的。
2. Volatile解決 : 強(qiáng)制線程每次在使用的時(shí)候,都會(huì)看一下共享區(qū)域最新的值,代碼示例如下:
package com.syh;public class Money{public static volatile int money = 1000;
}
package com.syh;public class MyThread1 extends Thread{@Overridepublic void run() {Money.money -= 100;System.out.println("李默然:" + Money.money);}
}
package com.syh;public class MyThread2 extends Thread{@Overridepublic void run() {System.out.println("林北辰:" + Money.money);}
}
package com.syh;public class Test {public static void main(String[] args) {MyThread1 t1 = new MyThread1();t1.start();MyThread2 t2 = new MyThread2();t2.start();}
}
2.2 synchronized解決
1. synchronized解決步驟 :
-
線程獲得鎖
-
清空變量副本
-
拷貝共享變量最新的值到變量副本中
-
執(zhí)行代碼
-
將修改后變量副本中的值賦值給共享數(shù)據(jù)
-
釋放鎖
2. 代碼實(shí)現(xiàn) :
package com.syh;public class Money{public static Object lock = new Object();public static int money = 1000;
}
package com.syh;public class MyThread1 extends Thread{@Overridepublic void run() {synchronized (Money.lock){Money.money -= 100;System.out.println("李默然: " + Money.money);}}
}
package com.syh;public class MyThread2 extends Thread{@Overridepublic void run() {synchronized (Money.lock){System.out.println("林北辰:" + Money.money);}}
}
package com.syh;public class Test {public static void main(String[] args) {MyThread1 t1 = new MyThread1();t1.start();MyThread2 t2 = new MyThread2();t2.start();}
}
2.3 原子性
???????原子性就是要么所有的操作都執(zhí)行,要么所有的操作都不執(zhí)行,多個(gè)操作是一個(gè)不可以分割的整體。
2.4 AtomicInteger類
java從JDK1.5開始提供了AtomicInteger類,這個(gè)包中的原子操作類提供了一種用法簡單,性能高效,線程安全地更新一個(gè)變量的方式,常用方法如下:
public AtomicInteger(): // 1.初始化一個(gè)默認(rèn)值為0的原子型Integer
public AtomicInteger(int initialValue): // 2.初始化一個(gè)指定值的原子型Integerint get(): // 3.獲取值
int getAndIncrement(): // 4.以原子方式將當(dāng)前值加1,注意,這里返回的是自增前的值。
int incrementAndGet(): // 5.以原子方式將當(dāng)前值加1,注意,這里返回的是自增后的值。
int addAndGet(int data): // 6.以原子方式將輸入的數(shù)值與實(shí)例中的值(AtomicInteger里的value)相加,并返回結(jié)果。
int getAndSet(int value): // 7.以原子方式設(shè)置為newValue的值,并返回舊值。
代碼實(shí)現(xiàn) :
package com.syh;import java.util.concurrent.atomic.AtomicInteger;public class MyAtom {public static void main(String[] args) {AtomicInteger ac = new AtomicInteger();System.out.println(ac);AtomicInteger ac2 = new AtomicInteger(10);System.out.println(ac2);}
}
2.5 悲觀鎖和樂觀鎖
synchronized和CAS的區(qū)別是什么?
1. 相同點(diǎn)
???????在多線程情況下,都可以保證共享數(shù)據(jù)的安全性。
2.不同點(diǎn)
-
悲觀鎖:synchronized總是從最壞的角度出發(fā),認(rèn)為每次獲取數(shù)據(jù)的時(shí)候,別人都有可能修改。所以在每次操作共享數(shù)據(jù)之前,都會(huì)上鎖。
-
樂觀鎖:cas是從樂觀的角度出發(fā),假設(shè)每次獲取數(shù)據(jù)別人都不會(huì)修改,所以不會(huì)上鎖。只不過在修改共享數(shù)據(jù)的時(shí)候,會(huì)檢查一下,別人有沒有修改過這個(gè)數(shù)據(jù)。