1.線程生命週期java
(1) 新建算法
(2) 就緒編程
(3) 運行安全
(4) 阻塞:1.正常切換 2.sleep()方法 3.wait()方法 4.執行某個操做進入阻塞狀態(等待IO、等待某個通知、試圖得到一個同步監視器等)併發
(5) 死亡spa
2.建立線程的方法線程
(1)繼承Thread類rest
(2)實現Runnable接口code
(3)使用Callable和Future建立線程orm
import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class Main implements Callable<Integer>{ public static void main(String[] args) { Main main = new Main(); FutureTask<Integer> task = new FutureTask<Integer>(main); new Thread(task, "子線程").start(); try { System.out.println("子線程返回值:"+ task.get()); } catch(Exception e) { e.printStackTrace(); } } public Integer call() throws Exception { int i = 0; for(; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"的變量i的值:"+i); } return i; } }
比較:Runnable與Callable方式基本相同,只是Callable接口裏定義的方法有返回值,能夠聲明拋出異常而已。
因此暫時將二者歸爲同一種方式。這種方式與繼承Thread類的主要區別爲:
(1)線程實現了Runnable接口,還能夠繼承其餘類
(2)多個線程能夠共享同一個target對象,多個線程共享該對象的成員變量
3.目標對象與線程的關係(後續上代碼解釋)
(1)目標對象與線程徹底解耦
(2)目標線程組合線程(弱耦合)
4.線程優先級與調度管理
(1)Java線程的優先級都在常數1~10的範圍內,默認爲5。
(2)setPriority(int)和getPriority()。
(3)Java調度器的任務是使高優先級的線程能始終運行,一旦時間片有空閒,則使具備同等優先級的線程以輪流的方式順序使用時間片。在實際編程中,不提倡使用線程的優先級來保證算法的正確執行。
5.線程控制方法
(1)sleep(int millsecond):單位毫秒
(2)yield():與sleep()方法類似,稱爲線程讓步,使線程暫停,但不會阻塞線程,只是將線程轉入就緒狀態,讓系統的調度器從新調度一次。
與sleep()區別:sleep()方法暫停當前線程,會給其餘線程機會,不理會其餘線程的優先級;但yield()方法只會給有優先級相同或更高的線程執行機會。
sleep()方法將線程轉入阻塞狀態;而yield()方法將線程轉入就緒狀態
(3)isAlive():檢查線程是否處於運行狀態的方法
注意:一個已經運行的線程在沒有進入死亡狀態時,不要再給線程分配線程實體,因爲線程只能引用最後分配的實體,先前的實體就會變成「垃圾」,而且不會被垃圾收集器收集。
(4)interrupt()
(5)join():稱爲線程聯合
一個線程A在佔用CPU資源期間,可讓其餘線程調用join()和本線程聯合,如B.join();
咱們稱A在運行期間聯合了B,若是線程A在佔用CPU資源期間一旦聯合線程B,那麼A線程將馬上中斷執行,一直等到它聯合的線程B執行完畢,線程A再從新排隊等待CPU資源,以便恢復執行。若是A準備聯合的B已經結束,那麼B.join()不會產生任何效果。
(6)setDaemon(boolean on):稱爲後臺線程或守護線程
一個線程調用void setDaemon(boolean on)方法能夠將本身設置成一個守護線程。當程序中全部用戶線程已結束運行,即便守護線程的run()方法中還有須要執行的語句,守護線程也馬上結束執行。
6.線程同步方法
(1)synchronized關鍵字:
synchronized(obj)
{
//同步代碼塊
}
其中obj稱爲同步監視器
(2)同步鎖(Lock)(後續上代碼)
7.線程通訊方法
(1)wait()、notify()、notifyAll():適用於用synchronized修飾的方法或代碼塊
import java.util.Scanner; public class Main{ public static void main(String[] args) { A a = new A(); B b = new B(); Thread aThread = new Thread(a); Thread bThread = new Thread(b); aThread.start(); bThread.start(); while(true) { Scanner reader = new Scanner(System.in); int type = reader.nextInt(); if(type == 1) a.restart(); else if(type == 2) b.restart(); } } } class A implements Runnable { int number = 0; public void run() { while(true) { number++; System.out.println(Thread.currentThread().getName()+":number="+number); if(number%5 == 0) { System.out.println(Thread.currentThread().getName()+"掛起"); try { hangUp(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"恢復執行"); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void hangUp() throws InterruptedException { wait(); } public synchronized void restart() { notifyAll(); } } class B implements Runnable { int number = 0; public void run() { while(true) { number--; System.out.println(Thread.currentThread().getName()+":number="+number); if(number%10 == 0) { System.out.println(Thread.currentThread().getName()+"掛起"); try { hangUp(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"恢復執行"); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void hangUp() throws InterruptedException { wait(); } public synchronized void restart() { notifyAll(); } } //控制檯輸入1喚醒子線程aThread,2喚醒子線程bThread
(2)Conditon:程序使用Lock來同步,系統中存在隱式的同步監視器,也就不能用wait()、notify()方法,此時可以使用Condition方法:await()、signal()、signalAll()。
(3)阻塞隊列(BLockingQueue):特別適合於生產者消費者問題
8.線程池:(後續上代碼)
(1)Excutors:
(2)ForkJoinPool:特別適用於多CPU作並行處理
9.線程相關類
(1)ThreadLocal:表明一個線程局部變量,讓每個線程建立該變量的副本,從而避免併發訪問的線程安全問題
(2)使用Collections提供的靜態方法把集合包裝成線程安全的集合,例如:
HashMap h = Collections.synchronizedMap(new HashMap());
(3)ConcurrentHashMap、CopyOnWriteArrayList等