Java併發程式設計入門
前言
隨著多核處理器的發展,已經從當年的遙不可及變得家喻戶曉;目前市場上的絕大多數中高檔計算機都是採用多核處理器,因此對多核處理器的利用變得普遍起來,在java程式設計中,針對多核處理器的併發程式設計慢慢的被java程式設計師所接受,Java併發程式設計已成為目前Java程式設計師必須掌握的一項關鍵性技能;Java併發程式設計可以讓軟體應用等更加高效的執行,本章將由淺入深的介紹Java的併發程式設計。
1.1執行緒基礎
程序: 資源分配的最小單位
執行緒:Cpu排程的最小單位,共享程序中的資源,必須依附於程序
並行:同一時刻執行進行的任務
併發:與時間有關,在單位時間段內處理的任務數
高併發程式設計的意義、好處和注意事項 :
1、充分利用cpu的資源
2、加快使用者響應的時間
3、模組化、非同步化
1.1.1三種建立/使用執行緒的方法
1.1.1.1建立
//繼承Thread private static class useThread extends Thread { @Override public void run() { super.run(); System.out.println("useThread extends Thread has running...."); } } //實現Runnable介面 private static class useRunnable implements Runnable { @Override public void run() { System.out.println("useRunnable implements Runnable has running...."); } } //實現Callable介面 private static class useCallable implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("useCallable implements Callable has running...."); return 5201314; } }
1.1.1.2 使用
//繼承Thread useThread use_thread=new useThread(); use_thread.start(); //實現Runnable介面 useRunnable use_runnable=new useRunnable(); Thread runnableThread=new Thread(use_runnable); runnableThread.start(); //實現Callable介面 useCallable use_callable=new useCallable(); FutureTask<Integer> futureTask=new FutureTask<>(use_callable); //包裝 Thread callableThread=new Thread(futureTask); //傳入Thread callableThread.start(); Integer integer=futureTask.get(); //取出資料
說明:Callable介面這種方法我們接觸的較少,這種與Runnable差不多,只是多了一個回傳資料的功能,Callable介面要用FutureTask來封裝後再用Thread生成呼叫start(),利用FutureTask可以取的回傳的資料。
1.1.2執行緒補充
讓Java裡的執行緒安全停止工作
interrupt() 不會去中斷執行緒,只是把一箇中斷標誌位置為true
isInterrupted()、static方法interrupted() 來檢查中斷標誌位
interrupt()方法讓執行緒安全中斷,在run()方法中使用sleep方法會丟擲InterruptException的異常,這時候需要在catch中重新將中斷標誌位置為true,即再次interrupt()一下,才可以正常使用interrupt()方法正常安全停止執行緒。
執行緒常用方法和執行緒的狀態
Yield方法,是讓當前執行緒讓出cpu時間,os依然可以選中當前執行緒
Join方法,當前執行緒A等待thread執行緒終止之後才從thread.join()返回。執行緒Thread除了提供join()方法之外,還提供了join(long millis)和join(longmillis,int nanos)兩個具備超時特性的方法。這兩個超時方法表示,如果執行緒thread在給定的超時時間裡沒有終止,那麼將會從該超時方法中返回。
ThreadLocal型別:
ThreadLocal型別的變數是所有執行緒共享的,且不會應為一個執行緒對其更改而影響其他執行緒的呼叫(還是呼叫原來的值)
private static final ThreadLocal<Integer> threadId =
new ThreadLocal<Integer>() {
@Override protected Integer initialValue() {
return 1;
}
};
Volatile型別:
volatile型別的變數是所有執行緒共享的,但會應為一個執行緒對其更改而影響其他執行緒的呼叫(呼叫更改後的值)---(可見性)
Volatile只保證記憶體可見性,不保證操作的原子性;某個變數 只有一個執行緒進行修改,其他的執行緒都是讀取,這個時候要求可見性,低原子性:Volatile
private volatile int age = 100000; //定義賦值
正是因為Volatile的這種特點,當多個執行緒對同一個Volatile操縱時會更加容易產生執行緒安全性問題。
額外乾貨:
併發程式正確地執行,必須要保證原子性、可見性以及有序性。只要有一個沒有被保證,就有可能會導致程式執行不正確:
原子性:一個操作或多個操作要麼全部執行完成且執行過程不被中斷,要麼就不執行。Java.util.concurrent.atomic包中包括了原子變數類,這些類用來實現數字和物件引用的原子狀態轉換。
可見性:當多個執行緒同時訪問同一個變數時,一個執行緒修改了這個變數的值,其他執行緒能夠立即看得到修改的值。
有序性:程式執行的順序按照程式碼的先後順序執行。
對於單執行緒,在執行程式碼時jvm會進行指令重排序,處理器為了提高效率,可以對輸入程式碼進行優化,它不保證程式中各個語句的執行先後順序同程式碼中的順序一致,但是它會保證儲存最終執行結果和程式碼順序執行的結果是一致的。
原文連結:https://blog.csdn.net/u010796790/article/details/52155664
執行緒的優先順序
通過一個整型成員變數priority來控制優先順序,優先順序的範圍從1~10,預設優先順序是5,在不同的JVM以及作業系統上,執行緒規劃會存在差異,有些作業系統甚至會忽略對執行緒優先順序的設定。
守護執行緒(瞭解)
Daemon執行緒是一種支援型執行緒,因為它主要被用作程式中後臺排程以及支援性工作。這意味著,當一個Java虛擬機器中不存在非Daemon執行緒的時候,Java虛擬機器將會退出。可以通過呼叫Thread.setDaemon(true)將執行緒設定為Daemon執行緒。我們一般用不上,比如垃圾回收執行緒就是Daemon執行緒。
Daemon執行緒被用作完成支援性工作,但是在Java虛擬機器退出時Daemon執行緒中的finally塊並不一定會執行。在構建Daemon執行緒時,不能依靠finally塊中的內容來確保執行關閉或清理資源的邏輯。
下接Java併發程式設計高階部分:
謝謝閱讀!歡迎評論交流!