Java多线程机制
//操作系統可以產生多個進程,每個進程也可以產生多個線程
1.線程
//"主線程”是main線程
//線程有4種狀態:新建、運行、中斷、死亡
(1)新建:
①通過繼承Thread類創建:
需要重寫Thread類的run()方法;
//優點:可以在子類中增加新的成員變量和方法,使線程具有某種屬性和功能。
? 缺點:Java不支持多繼承,Thread類的子類不能再擴展其他的類。
?
②通過實現Runnable接口創建:
構造方法:Thread(Runnable target)
//優點:對于使用同一目標對象的線程,目標對象的成員變量是這些線程共享的數據單元;
?創建目標對象的類在必要時可以是某個特定類的子類。
因此使用Runnable接口比使用Thread的子類更具有靈活性。
?
?
中斷原因:
①JVM將CPU資源從當前線程切換給其他線程,使本線程讓出CPU的使用權處于中斷狀態。
②線程使用CPU資源期間,執行了sleep(int millsecond)方法,使當前線程進入休眠狀態。
③線程使用CPU資源期間,執行了wait()方法,使得當前線程進入等待狀態。
④線程使用CPU資源期間,執行某個操作進入阻塞狀態,比如執行讀/寫操作引起阻塞。
?
死亡(線程釋放了實體和線程對象的內存)原因:
①執行完run()方法中的全部語句,結束了run()方法。
②線程被提前強制性地終止,即強制run()方法結束。
?
目標對象與線程的關系:
①完全解耦:目標對象沒有組合線程對象。
②弱耦合:目標對象可以組合線程,即將線程作為自己的成員(在Thread子類或實現Runnable的類中創建線程)。
//在實際問題中,根據實際情況確定目標對象和線程是組合或完全解耦關系,兩種關系各有優缺點。
?
線程的常用方法:
1.start() throws IllegalThreadStateException
啟動線程,二次調用start()方法會導致異常;
2.run()
定義線程對象被調度之后所執行的操作,系統自動調用而用戶程序不得引用;
3.sleep(int millsecond) throws InterruptedException
參數millsecond是以毫秒為單位的休眠時間,如果線程在休眠時被打斷,JVM就拋出異常;
4.isAlive()
判斷線程是否存在(非新建和死亡狀態);
5.currentThread()
返回當前正在使用CPU資源的線程;
6.interrupt()
"吵醒"休眠的線程,導致休眠的線程發生InterruptedException異常;
7.setPriority(int grade) throws IllegalArgumenException
調整線程的優先級,參數grade參數為1~10之間,若不在該范圍則發生異常(注意有些os只識別3個級別:1、5和10);
//實際編程中,不提倡使用線程的優先級來保證算法的正確執行
?
2.線程同步(用synchronized修飾)
線程同步機制:當一個線程A使用synchronized方法時,其他線程想使用這個synchronized方法時就必須等待,直到線程A使用完該synchronized方法。
同步方法中的方法(都是Object類的final方法):
1.wait()
中斷線程的執行,使本線程等待,暫時讓出CPU的使用權;
2.notify()
通知處于等待中的某一個線程結束等待;
3.notifyAll()
通知所有由于使用這個同步方法而處于等待的線程結束等待,曾中斷的線程從剛才的中斷處繼續執行這個同步方法;
//不可以在非同步方法中使用上述的三個方法
//遵循"先中斷先繼續”的原則
?
3.線程聯合
一個線程A在占有CPU資源期間,可以讓其他線程調用join()方法和本線程聯合,如:B.join();
如果線程A在占有CPU資源期間一旦聯合B線程,那么A線程將立刻中斷執行,一直等到它聯合的B線程執行完畢,A線程再重新排隊等待CPU資源,以便恢復執行。
//如果A準備聯合的B線程已經結束,那么B.join()不會產生任何效果。
?
4.GUI線程
當Java程序包含GUI時,JVM在運行程序時會自動啟動更多的線程,其中兩個重要的線程:AWT-EventQuecue和AWT-Windows
當觸發ActionEvent事件時,AWT-EventQuecue線程就立刻等候執行處理事件的代碼。
?
5.計時器線程
javax.swing.Timer類(避免與java.util.Timer類混淆):
構造方法:
Timer(int a)
必須調用addActionListener(ActionListener listener)方法獲得監視器(必須是組件類);
Timer(int a,Object b)
參數a的單位是毫秒,確定計時器每隔a毫秒"振鈴"一次,參數b是計時器的監視器;
?
常用方法:
1.setReapeats(boolean b)
只想計時器振鈴一次,可以調用此方法,參數b取值false;
2.setInitialDelay(int depay)
設置首次振鈴的延時,默認延時為a;
3.start()
啟動計時器;
4.stop()
停止計時器,即掛起線程;
5.restart()
重新啟動計時器,即恢復線程;
?
6.守護線程
線程默認是非守護線程(用戶線程),一個線程調用void setDaemon(boolean on)方法將自己設置成一個守護線程,如:thread.setDaemon(true);
當所有用戶線程結束運行時, 即使守護線程的run方法還未執行完,也立刻結束運行。
//守護線程用來做一些不是很嚴格的工作
轉載于:https://www.cnblogs.com/rongbin/p/9390158.html
總結
- 上一篇: vagrant 简单使用
- 下一篇: [转]linux各文件夹介绍