1. 程式人生 > >Java執行緒及執行緒池

Java執行緒及執行緒池

Java執行緒及執行緒池

什麼是執行緒安全

  1. 多個任務同時執行,不會出問題
  2. 類的全域性變數和靜態變數在多個執行緒同時訪問時,如果只有讀為執行緒安全,如果有寫,則可能出現執行緒不安全

建立執行緒的3種方式

  1. 繼承Thread類,並重寫run()方法
  2. 實現Runnable介面,並實現run()方法
  3. 實現Callable介面,有返回值

Runnable介面和Callable介面的區別

一個有返回值,一個沒有

wait方法和sleep方法的區別

wait會讓出執行緒鎖,讓別的執行緒先執行,sleep不會

介紹下CAS(無鎖技術),什麼是悲觀鎖和樂觀鎖

  1. CAS是CPU的指令,將比較和轉換做為一個原子操作,如果比較的結果是預期結果就是轉換,否則不做任何操作。但是,這會出現另一個問題:ABA,即會出現在CAS執行時,雖然比較結果是成功的,但不知道這個結果是否已經被改過新值又改回原值,故可以用AtomicStampedReference,在初始化時新增一個版本號,比較時也比較版本號來保證沒有被修改過
  2. 悲觀鎖:synchronized鎖,即在執行多執行緒程式碼時,會出現競爭問題,先給這段程式碼上鎖
  3. 樂觀鎖:CAS鎖,操作為原子性,如果失敗,通過死迴圈來重複執行,直到成功達到預期

volatile關鍵字的作用和原理

volatile是輕量級的同步鎖,但不是原子性的,因為這個關鍵字是在主記憶體中,每個得到鎖的執行緒在執行時,會先從主記憶體中把這個值放到自己的執行緒工作記憶體中,因此會出現不準確的同步。同時,這個關鍵字也會防止指令重排,保證化修飾的變數不會出現指令重排。

什麼是ThreadLocal

  1. ThreadLocal是Thread中的一個變數,可以叫做執行緒本地變數,用來儲存執行緒中的一個物件,如在多執行緒環境中,每個執行緒有session、connection等,只要有任務過來,就可以立即用自己執行緒ThreadLoacl中的儲存的物件進行操作,不必從主執行緒或者主記憶體中取資料,即中空間換取時間,來提高執行速度。
  2. 在儲存ThreadLoacl中使用的是類似HashMap的一個ThreadLocalMap,對執行緒隔離後,每個執行緒儲存物件的一個執行緒私有變數。

建立執行緒池的4種方式

  1. Executors.newCachedThreadPool():快取執行緒池,沒有初始數,最大為Integer.MAX
  2. Executors.newFixedThreadPool(2):固定數執行緒池,初始值即為最大值,有一個連結串列佇列
  3. Executors.newSingleThreadExecutor():單執行緒池,有一個連結串列佇列
  4. Executors.newWorkStealingPool():

執行緒池啟動的引數解釋

new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

  1. 初始個數:執行緒池中的初始執行緒個數,必須大於0
  2. 最大個數:執行緒池中的最大執行緒個數,不能小於初始執行緒個數
  3. 存活時間:超過初始執行緒數後的那些執行緒存活時間
  4. 時間單位:3的時間單位
  5. 任務佇列:當執行緒池中的個數為最大執行緒數時,新來的任務將放到該佇列中
  6. 執行緒工廠:用來啟動執行緒,自定義執行緒名字等
  7. 滿隊策略:當佇列滿後,執行的異常策略
任務佇列:
  1. ArrayBlockingQueue:是一個基於陣列結構的有界阻塞佇列,按FIFO原則進行排序
  2. LinkedBlockingQueue:一個基於連結串列結構的阻塞佇列,吞吐量高於ArrayBlockingQueue。靜態工廠方法Executors.newFixedThreadPool()使用了這個佇列
  3. SynchronousQueue: 一個不儲存元素的阻塞佇列。每個插入操作必須等另一個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態,吞吐量高於LinkedBlockingQueue,靜態工廠方法Executors.newCachedThreadPool()使用了這個佇列
  4. PriorityBlockingQueue:一個具有優先順序的無限阻塞佇列。