標籤:
------- android培訓、java培訓、期待與您交流! ----------
Lock()實現提供了比使用synchronized方法和語句可獲得更廣泛的鎖定操作。
private Lock lock =new ReentrantLock();
被鎖的代碼要用 lock.lock() lock.unlock() 包括。其中用try 。。。finally包圍
同步:效率低,如果出現同步嵌套,會出現死結。 但是安全。
死結問題:兩個或者兩個以上的線程在爭奪資源的過程中,發生的一種相互等待的現象
線程間通訊,不同種類的線程針對同一資源的操作。
多線程還可能出現同一個資料出現多次,或者輸出不匹配問題。都屬於安全執行緒問題。
等待 喚醒機制
Object類中wait()等待 notify()喚醒單個線程 notifyAll()喚醒所有線程
這些方法調用必須通過鎖對象調用,二我們剛才使用的鎖對象是任意鎖對象。
wait()要用try catch包圍 用喚醒notify()來解決死結
即一個run()裡判斷一個條件,如果成立就鎖調用wait(),如果不成立,鎖的判斷條件改變,然後調用notify()喚醒。
運行狀態圖:
線程組:預設情況下是main線程組
getThreadGroup()獲得線程組
Thread.currentThread().getThreadGroup().getName();返回線程組的名字。
改變線程組
首先建立一個線程組:ThreadGroup tg=new ThreadGroup("這是一個新的線程組");
然後Thread t1=new Thread(tg,Myrunnale,"線程名");
通過線程組名稱設定後台線程,tg.setDaemon() 設定守護線程。等等
線程組主要是對線程統一管理。
同步還可以在類裡,把相應的方法設定成synchronized 注意方法裡面的鎖的對象是this
線程池:程式啟動一個新線程成本是比較高的,因為它涉及到要與作業系統進行互動,二使用線程池可以很好的提高效能,尤其是當程式中要建立大量生存周期很短的線程時,更應該考慮使用線程池。
線程池每個線程結束後不會銷毀,而是回到線程池變成空閑狀態。
-
static ExecutorService |
newCachedThreadPool() 建立一個可根據需要建立新線程的線程池,但是在以前構造的線程可用時將重用它們。 |
-
static ExecutorService |
newFixedThreadPool(int nThreads) 建立一個可重用固定線程數的線程池,以共用的無界隊列方式來運行這些線程。 |
static ExecutorService |
newSingleThreadExecutor() 建立一個使用單個 worker 線程的 Executor,以無界隊列方式來運行該線程。 |
A:建立一個線程池對象,控制要建立幾個線程對象
ExecutorServoce newFixedThreadPool(int nThread)
B:這種線程池的線程可以執行:
可以執行Runnable對象或者CallAble對象代表的線程
做一個實現Runnable介面
C:調用如下方法即可:
Future<?> submit(Runnable task)
<T> Future<T> submit(Callable<T> task)
newFixedThreadPool靜態函數,直接調用
1 ExecutorService pool=Executors.newFixedThreadPool(2);2 pool.submit(new MyRunnable);
- 結束線程池:pool.shutdown();
- 建立多線程方式3:
Callable是個介面 這個線程有返回介面,但是runnable沒有返回結果。 跟 Runnable用法相似
他是通過線程池來建立線程。 這個不常見
- Future 表示submit非同步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並擷取計算的結果。計算完成後只能使用 get 方法來擷取結果,如有必要,計算完成前可以阻塞此方法。取消則由 cancel 方法來執行。 麻煩,一般不用。
- 匿名內部類使用多線程“
1 //整合Thread類來實現多線程 2 new Thread(){ 3 public void run() { 4 for (int i = 0; i < 100; i++) { 5 System.out.println(Thread.currentThread().getName()+":"+i); 6 } 7 }; 8 }.start(); 9 //用Runnable介面實現10 new Thread(new Runnable() {11 12 @Override13 public void run() {14 // TODO Auto-generated method stub15 for (int i = 0; i < 100; i++) {16 System.out.println(Thread.currentThread().getName()+":"+i);17 }18 }19 }){}.start();
- 但是對於,走的是子類的,即會輸出world,不會輸出hello
1 new Thread(new Runnable() { 2 3 @Override 4 public void run() { 5 // TODO Auto-generated method stub 6 for (int i = 0; i < 100; i++) { 7 System.out.println("hello"+":"+i); 8 } 9 }10 }){11 public void run() {12 for (int i = 0; i < 100; i++) {13 System.out.println("world"+":"+i);14 }15 };16 }.start();
定時器:在指定時間做某件事或者重複某件事
Timer 一種工具,線程用其安排以後在後台線程中執行的任務。可安排任務執行一次,或者定期重複執行。
- 依賴Timer和TimerTask兩個類
Timer 定時
TimerTask :任務
-
| ?構造方法摘要 |
Timer() 建立一個新計時器。 |
|
timer方法
| |
cancel() 終止此計時器,丟棄所有當前已安排的任務。 |
int |
purge() 從此計時器的任務隊列中移除所有已取消的任務。 |
void |
schedule(TimerTask task, Date time) 安排在指定的時間執行指定的任務。 |
void |
schedule(TimerTask task, Date firstTime, long period) 安排指定的任務在指定的時間開始進行重複的固定順延強制。 |
void |
schedule(TimerTask task, long delay) 安排在指定延遲後執行指定的任務。 |
void |
schedule(TimerTask task, long delay, long period) 安排指定的任務從指定的延遲後開始進行重複的固定順延強制。 |
void |
scheduleAtFixedRate(TimerTask task, Date firstTime, long period) 安排指定的任務在指定的時間開始進行重複的固定速率執行。 |
void |
scheduleAtFixedRate(TimerTask task, long delay, long period) 安排指定的任務在指定的延遲後開始進行重複的固定速率執行。
|
- 面試題
1:多線程有幾種實現方案,分別是哪幾種? 兩種。 繼承Thread類 實現Runnable介面 擴充一種:實現Callable介面。這個得和線程池結合。 2:同步有幾種方式,分別是什麼? 兩種。 同步代碼塊 同步方法 3:啟動一個線程是run()還是start()?它們的區別? start(); run():封裝了被線程執行的代碼,直接調用僅僅是普通方法的調用 start():啟動線程,並由JVM自動調用run()方法 4:sleep()和wait()方法的區別 sleep():必須指時間;不釋放鎖。 wait():可以不指定時間,也可以指定時間;釋放鎖。 5:為什麼wait(),notify(),notifyAll()等方法都定義在Object類中 因為這些方法的調用是依賴於鎖對象的,而同步代碼塊的鎖對象是任意鎖。 而Object代碼任意的對象,所以,定義在這裡面。 6:線程的生命週期圖 建立 -- 就緒 -- 運行 -- 死亡 建立 -- 就緒 -- 運行 -- 阻塞 -- 就緒 -- 運行 -- 死亡 建議:畫圖解釋。
黑馬程式員——JAVA基礎之Day24 多線程 ,死結,線程間通訊 ,線程組,線程池,定時器。