摘要:另外一種方法是,將這個線程加入一個線程組,在線程組里重寫方法來處理拋出的異常,這時線程組的作用相當于實現了的類。使用對象處理異常格式錯誤使用線程組處理異常測試異常
感性地理解一下什么是線程?
線程這個概念其實是比較抽象的,雖然依照教科書上的說法:
進程是從系統獲取資源的最小單位,線程是程序執行的最小單位。程序是靜態存在于磁盤上的一段文本,進程運行這段文本記錄的命令。
也就是說,進程從系統那里獲取到了一定的CPU占用時間片、內存單元和IO等等資源,然后線程將這些資源利用起來執行程序,線程執行程序是什么意思呢?就是把程序記錄的那些命令逐條依序一步步在CPU上運作,數據在內存、IO上流轉,將命令執行完。
這個層級的概念存在于OS上,OS的調度抽象層級并不是那么直觀,如果我們在說明白一點,在做底層的計算機組成原理實驗的時候,在我們接好連線后硬件就具有了處理數據的能力,只要扳動不同的開關就可以將數據讀寫在不同的芯片上,我們的程序也許是為了完成數據流轉寫在紙上的扳動不同開關的序列,所以程序是屬于IO級別的,然后我們依照紙上的命令序列實際上手去扳動不同的開關執行的就是這段程序,所以我們自己充當的角色就是進程,最終就得出了這樣的結論:進程“執行”程序。至于線程呢,可以看作是進程在執行過程中的策略,比如說在一個人扳動開關的時候就是單進程單線程,如果是兩個人扳動開關就是單進程多線程,如果兩個人能配合起來扳動開關就是多線程同步,所以線程和進程之間并非互斥的概念,而是相容的概念,如果有線程就一定有進程,一個進程包含了至少一個的線程。
創建線程的方法
1.創建直接創建Thread的子類,重寫run()方法;
class MyThread extends Thread { @Override public void run() { System.out.println("This is my thread"); } } public class Test { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); } }
2.創建一個線程執行類實現Runnable接口,在這個執行類里實現Runnable的run()方法,創建該執行類的對象后,用此執行類對象初始化新線程,啟動新線程時即執行這個執行對象的run()方法;
class MyRunnable implements Runnable { @Override public void run() { System.out.println("This is my thread"); } } public class Test { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); } }
3.通過線程工廠用工廠模式來創建新線程,新建工廠類繼承ThreadFactory類重寫newThread()方法,通過指定實現了Runnable接口的執行類來創建與之對應的線程;
public class ThreadFactoryDemo { public static void main(String[] args) { ThreadFactory factory = new ThreadFactory() { @Override public Thread newThread(Runnable r) { // TODO Auto-generated method stub return new Thread(r); } }; factory.newThread(new Runnable() { @Override public void run() { System.out.println("in runnable."); } }).start(); } }
注意:只有調用Thread類的Start方法,才能真正地在一個獨立的線程中執行代碼,直接調用Thread類的run方法,并不能啟動一個新的線程,代碼是在調用者線程中執行的。
那么主線程的run()方法在哪里呢?任何java程序的main執行入口擔當著啟動主線程的作用,只要進入了main函數就執行了主線程,因此整個main函數里的內容就是主線程的run()方法。
線程究竟執行哪個run()方法
當線程同時具有可執行對象實現的run()方法和線程重寫的run()方法時,啟動線程時究竟執行哪個run()方法呢?
結果是如果只定義了可執行對象的run()方法則執行這個run()方法,如果只重寫了線程的run()方法則執行這個run()方法,如果兩個方法都有則執行線程重寫的run()方法。
public class Test { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("Runnable.run()"); } }) { @Override public void run() { // TODO Auto-generated method stub System.out.println("Thread.run()"); } }; thread.start(); } }
線程的休眠
使用Thread類的sleep()方法或者使用TimeUnit的相關方法來休眠線程,休眠的意思是資源仍被占用,但是線程保留原來的狀態沒有活動;
public class ThreadSleep { public static void main(String[] args) { Thread th = new Thread(new Runnable() { public void run() { for (int i = 0; i < 10; i++) { try { // Thread.sleep(500); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }); th.start(); } }
線程中斷
線程中斷的意思是線程停止當前的運行狀態讓出資源結束生命周期,當外界想要一個線程中斷時需要調用它的interrupted()方法,調用后不是直接就可以中斷這個線程,而是將線程的interrupted標記位賦為1,如果要線程要響應這個中斷則定期需要檢查這個標記,檢查到被中斷標記后自己退出執行狀態。
public class ThreadInterruptDemo { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread() { @Override public void run() { while (true) { System.out.println("running"); if (isInterrupted()) return; } } }; thread.start(); Thread.sleep(2000); thread.interrupt(); } }
線程定時任務
線程要實現定時任務的話可以使用Runnable的實現類TimerTask,此類需要重寫run()方法以完成具體需要進行的定時任務。然后由定時器Timer來調度,使用Timer的schedle()方法相當于啟動這個定時任務線程。
public class TimerTaskDemo { public static void main(String[] args) { TimerTask task = new TimerTask() { private int counter = 0; @Override public void run() { System.out.println(counter + ":invoked!"); counter++; } }; Timer timer = new Timer(); // 過2秒鐘后首次運行,以后每隔3秒運行一次 timer.schedule(task, 2000, 3000); } }
線程運行過程中的異常處理
線程的run()方法中是不允許直接拋出異常的,也就是說不能有這樣的寫法:run() throws Exception ,原因在于在線程的運行過程中應該最大限度地保持正常工作,因此除了一些不可預知的運行時異常,不應該主動拋出受控異常。如果非要在run()方法里處理拋出的異常,則應該定義一個實現了UncaughtExceptionHandler的類,然后指定這個類的對象在重寫的uncaughtException()方法里去處理拋出的異常。另外一種方法是,將這個線程加入一個線程組,在線程組里重寫uncaughtException()方法來處理拋出的異常,這時線程組的作用相當于實現了UncaughtExceptionHandler的類。
1.使用handler對象處理異常:
public class ThreadTest { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { throw new RuntimeException("格式錯誤"); } }); thread.setUncaughtExceptionHandler(new MyHandler()); thread.start(); } } class MyHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(t.getName() + ":" + e.getMessage()); } }
2.使用線程組處理異常:
public class ThreadGroupDemo { public static void main(String[] args) { ThreadGroup threadGroup1 = new ThreadGroup("group1") { public void uncaughtException(Thread t, Throwable e) { System.out.println(t.getName() + ": " + e.getMessage()); } }; Thread thread1 = new Thread(threadGroup1, new Runnable() { public void run() { throw new RuntimeException("測試異常"); } }); thread1.start(); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64617.html
摘要:線程可以被稱為輕量級進程。一個守護線程是在后臺執行并且不會阻止終止的線程。其他的線程狀態還有,和。上下文切換是多任務操作系統和多線程環境的基本特征。在的線程中并沒有可供任何對象使用的鎖和同步器。 原文:Java Multi-Threading and Concurrency Interview Questions with Answers 翻譯:并發編程網 - 鄭旭東 校對:方騰飛 多...
摘要:多線程和并發問題是技術面試中面試官比較喜歡問的問題之一。線程可以被稱為輕量級進程。一個守護線程是在后臺執行并且不會阻止終止的線程。其他的線程狀態還有,和。上下文切換是多任務操作系統和多線程環境的基本特征。 多線程和并發問題是 Java 技術面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應該牢固的掌握Java多線程基礎知識來對應日后碰到的問題。(...
摘要:超詳細的面試題總結一之基本知識多線程和虛擬機創建線程有幾種不同的方式你喜歡哪一種為什么繼承類實現接口應用程序可以使用框架來創建線程池實現接口。死亡線程方法執行結束,或者因異常退出了方法,則該線程結束生命周期。死亡的線程不可再次復生。 超詳細的Java面試題總結(一)之Java基本知識 多線程和Java虛擬機 創建線程有幾種不同的方式?你喜歡哪一種?為什么? 繼承Thread類 實現R...
摘要:一線程的基本概念單線程簡單的說,單線程就是進程中只有一個線程。多線程由一個以上線程組成的程序稱為多線程程序。當線程調用完方法進入后會自動釋放鎖,線程獲得鎖。 一、線程的基本概念 1.1 單線程 簡單的說,單線程就是進程中只有一個線程。單線程在程序執行時,所走的程序路徑按照連續順序排下來,前面的必須處理好,后面的才會執行。 Java示例: public class SingleThrea...
摘要:基礎知識復習后端掘金的作用表示靜態修飾符,使用修飾的變量,在中分配內存后一直存在,直到程序退出才釋放空間。將對象編碼為字節流稱之為序列化,反之將字節流重建成對象稱之為反序列化。 Java 學習過程|完整思維導圖 - 后端 - 掘金JVM 1. 內存模型( 內存分為幾部分? 堆溢出、棧溢出原因及實例?線上如何排查?) 2. 類加載機制 3. 垃圾回收 Java基礎 什么是接口?什么是抽象...
閱讀 947·2021-09-26 09:55
閱讀 3192·2021-09-22 15:36
閱讀 2982·2021-09-04 16:48
閱讀 3142·2021-09-01 11:41
閱讀 2591·2019-08-30 13:49
閱讀 1491·2019-08-29 18:46
閱讀 3546·2019-08-29 17:28
閱讀 3425·2019-08-29 14:11