多線程與高并發(fā)
線程
什么是線程
-
進(jìn)程
進(jìn)程相對(duì)于可執(zhí)行程序來(lái)說(shuō)是一個(gè)動(dòng)態(tài)概念击狮,比如磁盤上有一個(gè)QQ.exe程序,雙擊運(yùn)行就是一個(gè)進(jìn)程
-
線程
進(jìn)程是一個(gè)運(yùn)行的程序妇汗,線程則是程序不同的執(zhí)行路徑帘不,比如qq包含聊天,瀏覽空間屬于不同的線程
線程創(chuàng)建方式
-
Thread
通過(guò)繼承Thread類杨箭,重寫run方法:
MyThread myThread = new MyThread()
myThread.start()
-
Runnable
繼承Runnable 接口
MyThread{
}new Thread(new MyThread).start()
相比于繼承Thread實(shí)現(xiàn)線程創(chuàng)建寞焙,通過(guò)繼承方式有更好的擴(kuò)展性
-
Callable
實(shí)現(xiàn)Callable接口 重寫call方法,call方法有返回值
new Thread(new FutureTask<String>(new MyCallThread())).start()
線程狀態(tài)
- Ready
- Running
- Terminated
- TimedWaiting
- Waiting
- Blocked
線程通信
-
Thread
- wait() 會(huì)釋放鎖,必須在synchronized中使用
- notify() 不釋放鎖互婿,必須在synchronized中使用
-
LockSupport
- park()
- unpark(t)
鎖
volatile
-
保證可見(jiàn)性
在線程中捣郊,會(huì)拷貝變量的副本,修改操作基于副本進(jìn)行慈参,結(jié)束后講修改結(jié)果寫回原有變量呛牲,線程內(nèi)的修改對(duì)其他線程不可見(jiàn)
假設(shè)有A和B 兩個(gè)線程和變量C,volitale 修飾C驮配,A線程中對(duì)C的修改將會(huì)立馬作用在變量C上
-
禁止指令重排
在程序編譯的過(guò)程中娘扩,可能會(huì)對(duì)代碼進(jìn)行優(yōu)化着茸,雖然最終執(zhí)行結(jié)果一樣,但是執(zhí)行順序可能發(fā)生改變琐旁,在多線程環(huán)境中可能會(huì)出錯(cuò)涮阔。
-
double check 單例模式需不需要加volatile ?
需要,如果不加灰殴,指令重排可能導(dǎo)致問(wèn)題敬特。
public class DoubleCheck {
private static volatile DoubleCheck INSTANCE;
private DoubleCheck(){}public DoubleCheck getINSTANCE(){ if(INSTANCE == null){ synchronized (DoubleCheck.class){ if(INSTANCE == null) INSTANCE = new DoubleCheck(); } } return INSTANCE; }
}
synchronized
-
同步鎖
- 鎖方法
- 鎖代碼塊
- 鎖Object
-
鎖升級(jí)
首先加偏向鎖(在這個(gè)Object的頭上面markword記錄這個(gè)線程,即在第一個(gè)線程訪問(wèn)的時(shí)候?qū)嶋H上時(shí)沒(méi)有給這個(gè)Object加鎖的牺陶,在內(nèi)部實(shí)現(xiàn)的售后伟阔,只是記錄這個(gè)線程的ID(偏向鎖)),
如果有線程爭(zhēng)用的話掰伸,就升級(jí)為自旋鎖皱炉,
自旋鎖轉(zhuǎn)10次之后,升級(jí)為重量鎖狮鸭,重量所就是去操作心痛哪里申請(qǐng)資源娃承。
-
重入性
加鎖方法可以調(diào)用其他加鎖方法,
如果兩個(gè)方法存在嵌套調(diào)用關(guān)系怕篷,且持有同一把鎖历筝,則內(nèi)層方法可以直接執(zhí)行。
CAS
-
compare and swap
cas(V,Expectded,NewValue){
if V==E
V = NEW
otherwise try again or fail
}
Atomic類和線程同步新機(jī)制
Atomic
- AtomicInteger AtomicLong
- LongAdder
新機(jī)制
-
ReentranLock
ReentrantLock 可以替代synchronized是沒(méi)問(wèn)題的廊谓,也可以重入梳猪,是可以鎖定的。本身的底層是cas
- lock()
- unlock()
-
CountDownLatch
- 計(jì)數(shù)門閂
-
CylicBarrier
- 循環(huán)柵欄
-
Phaser
-
階段
更像是結(jié)合了CountDownLatch和CyclicBarrier蒸痹,
-
線程池
容器
面試過(guò)程中如何聊容器類
可以從兩大面開始聊春弥,容器分為兩大類Collection,Map,Collection又分為三大類:List Set Queue隊(duì)列叠荠,隊(duì)列即時(shí)一隊(duì)一隊(duì)的匿沛,往隊(duì)列里取數(shù)據(jù)時(shí)它和這個(gè)List Set 都不一樣。大家知道List取得時(shí)候如果Array的話還可以取到其中的一個(gè)榛鼎。Set主要和其他的區(qū)別就是中間時(shí)唯一的逃呼,不會(huì)有重復(fù)元素。Queue實(shí)現(xiàn)了一個(gè)什么邏輯呢者娱,實(shí)際上就是一個(gè)隊(duì)列抡笼,隊(duì)列什么概念,有進(jìn)有出黄鳍,那么再這個(gè)基礎(chǔ)之上推姻,它實(shí)現(xiàn)了許多的線程訪問(wèn)方法(比如put阻塞式的放,take阻塞式的瓤蚬怠)藏古,這個(gè)式其他的list set里沒(méi)有的增炭,隊(duì)列的最主要原因是為了實(shí)現(xiàn)任務(wù)的裝在的種種取和裝這里面最重要的就是叫做阻塞隊(duì)列,它的實(shí)現(xiàn)初衷是為了線程池高并發(fā)做準(zhǔn)備拧晕。
-
Collection
-
List
- CopyOnWriteList
- Vector
- ArrayList
- LinkedList
-
Set
-
HashSet
- LinkedHashSet
-
SortedSet
- TreeSet
EnumSet
CopyOnWriteArraySet
ConcurrentSkipListSet
-
-
Queue
Queue和List的區(qū)別到底在哪里弟跑,主要就是Queue添加了offer peek poll put take這些個(gè)對(duì)線程友好的或者阻塞或者等待的方法。
-
- Dequeue
- BlockingQueue
- ArrayBlockingQueue
- PriorityBlockingQueue
- LinkedBlockingQueue
- TransferQueue
- SynchronousQueue
- PriorityQueue
- DelayQueue
-
Map
-
HashMap
- LinkedHashMap
TreeMap
WeakHashMap
IdentityHashMap
ConcurrrentHashMap
ConcurrentSkipListMap
-
阻塞隊(duì)列
線程池
-
線程池7大參數(shù)
核心線程數(shù)
最大線程數(shù)
生存時(shí)間
生存時(shí)間單位
任務(wù)任務(wù)隊(duì)列
線程工廠
-
拒絕策略
-
Abort
拋異常
-
- Discard
扔掉 不拋異常
- DiscardOldest
扔掉排隊(duì)時(shí)間最久的
- CallerRuns
調(diào)用者處理服務(wù)
- 自定義拒絕策略
-
原理
-
分類
ThreadPoolExecutor
-
ForkJoinPool
Fork分叉防症,分叉完再分叉,最后結(jié)果匯總叫join
-
- ThreadPoolExecutor實(shí)現(xiàn)
Executor接口哎甲,接口把線程的定義和執(zhí)行分開
ExecutorService實(shí)現(xiàn)Executor接口蔫敲,定義線程池的生命周期方法
然后才是各種各樣的ThreadPoolExecutor : 把線程池作為一個(gè)執(zhí)行單元,給他單獨(dú)出來(lái)一個(gè)類
Executors 是工具類炭玫,生成各種線程池
XMind - Trial Version