Java線程介紹

      網友投稿 622 2025-03-31

      操作系統可以在同一時刻運行多個程序。例如一邊播放音樂,一邊下載文件和瀏覽網頁。操作系統將cpu的時間片分配給每一個進程,給人一種并行處理的感覺。

      一個多線程程序可以同時執行多個任務。通常,每一個任務稱為一個線程(thread),它是線程控制的簡稱。可以同時運行一個以上線程的程序成為多線程程序(multithreaded)。

      多進程和多線程有哪些區別呢?

      本質區別在于進程每個進程有自己的一整套變量,而線程則共享數據。

      線程比進程更輕量級,創建、銷毀一個線程比啟動新進程的開銷要小。

      實際應用中,多線程非常有用。例如應用一邊處理用戶的輸入指令,一遍聯網獲取數據。

      本文我們介紹Java中的Thread類。

      Thread

      Thread類屬于java.lang包。

      要創建一個線程很簡單,新建一個Thread對象,并傳入一個Runnable,實現run()方法。

      調用start()方法啟動線程。

      Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println("rustfisher said: hello"); } }); t1.start();

      Java lambda

      Thread t1 = new Thread(() -> System.out.println("rustfisher said: hello")); t1.start();

      不要直接調用run()方法;直接調用run()方法不會啟動新的線程,而是直接在當前線程執行任務。

      我們來看一個使用了Thread.sleep()方法的例子。

      Thread t1 = new Thread(() -> { for (String a : "rustfisher said: hello".split("")) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print(a); } }); t1.start();

      sleep(int)方法會讓線程睡眠一個指定的時間(單位毫秒)。并且需要try-catch捕獲InterruptedException異常。

      中斷線程

      當run()方法執行完最后一條語句后,或者return,或者出現了未捕獲的異常,線程將會終止。

      使用Thread的interrupt方法也可以終止線程。調用interrupt方法時,會修改線程的中斷狀態為true。

      用isInterrupted()可以查看線程的中斷狀態。

      但如果線程被阻塞了,就沒法檢測中斷狀態。當在一個被阻塞的線程(sleep或者wait)上調用interrupt方法,阻塞調用將會被InterruptedException中斷。

      被中斷的線程可以決定如何響應中斷。可以簡單地將中斷作為一個終止請求。比如我們主動捕獲InterruptedException。

      Thread t2 = new Thread(() -> { for (String a : "rustfisher said: hello".split("")) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("被中斷 退出線程"); return; } System.out.print(a); } }); t2.start(); new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } t2.interrupt(); }).start();

      上面這個小例子展示了用interrupt()來中斷線程t2。而線程t2的run()方法中捕獲InterruptedException后,可以進行自己的處理。

      線程的狀態

      線程有6種狀態,用枚舉類State來表示:

      NEW(新創建)

      RUNNABLE(可運行)

      BLOCKED(被阻塞)

      WAITING(等待)

      TIMED_WAITING(計時等待)

      Java線程介紹

      TERMINATED(被終止)

      用getState()方法可以獲取到線程的狀態。

      新創建線程

      new一個線程的時候,線程還沒開始運行,此時是NEW(新創建)狀態。在線程可以運行前,還有一些工作要做。

      可運行線程

      一旦調用start()方法,線程處于RUNNABLE(可運行)狀態。調用start()后并不保證線程會立刻運行,而是要看操作系統的安排。

      一個線程開始運行后,它不一定時刻處于運行狀態。操作系統可以讓其他線程獲得運行機會。一個可運行的線程可能正在運行也可能沒在運行。

      被阻塞和等待

      線程處于被阻塞和等待狀態時,它暫時不活動。不運行代碼,且只消耗最少的資源。直到線程調度器重新激活它。

      一個線程試圖獲取一個內部的對象鎖,而該鎖被其他線程持有,則這個線程進入阻塞狀態。當這個鎖被釋放,并且線程調度器允許這個線程持有它,該線程變成非阻塞狀態。

      當線程等待另一個線程通知調度器,它自己進入等待狀態。例如調用Object.wait()或者Thread.join()方法。

      帶有超時參數的方法可讓線程進入超時等待狀態。例如Thread.sleep(),Object.wait(long),Thread.join(long),Lock.tryLock(long time, TimeUnit unit)

      上面這個圖展示了狀態之間的切換。

      被終止

      終止的原因:

      run方法正常退出

      出現了沒有捕獲的異常而終止了run方法

      線程屬性

      線程優先級,守護線程,線程組以及處理未捕獲異常的處理器。

      線程優先級

      Java中每個線程都有一個優先級。默認情況下,線程繼承它的父線程的優先級。

      可用setPriority(int)方法設置優先級。優先級最大為MAX_PRIORITY = 10,最小為MIN_PRIORITY = 1,普通的是NORM_PRIORITY = 5。

      線程調度器有機會選新線程是,會優先選高優先級的線程。

      守護線程

      調用setDaemon(true)可以切換為守護線程(daemon thread)。守護線程的用途是為其他線程提供服務。例如計時線程。

      當只剩下守護線程是,虛擬機就退出了。

      守護線程不應該去訪問固有資源,如文件和數據庫。

      未捕獲異常處理器

      run()方法里拋出一個未捕獲異常,在線程死亡前,異常被傳遞到一個用于未捕獲異常的處理器。

      要使用這個處理器,需要實現接口Thread.UncaughtExceptionHandler,并且用setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)方法把它交給線程。

      Thread t3 = new Thread(() -> { try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); return; } int x = 0, y = 3; int z = y / x; // 故意弄一個異常 }); t3.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(t + "有未捕獲異常"); e.printStackTrace(); } }); t3.start();

      運行后,run()方法里拋出ArithmeticException異常

      Thread[Thread-0,5,main]有未捕獲異常 java.lang.ArithmeticException: / by zero at Main.lambda$main$0(Main.java:15) at java.lang.Thread.run(Thread.java:748)

      也可以用靜態方法Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)給所有的線程安裝一個默認處理器。可以在這個默認處理器里做一些工作,例如記錄日志。

      ThreadGroup代表著一組線程。也可以包含另外的線程組。

      ThreadGroup類實現了UncaughtExceptionHandler接口。它的uncaughtException(Thread t, Throwable e)方法會有如下操作

      如果該線程組有父線程組,則父線程組的uncaughtException被調用。

      否則,如果Thread.getDefaultUncaughtExceptionHandler()返回一個非空處理器,則使用這個處理器。

      否則,如果拋出的Throwable是ThreadDeath對象,就什么也不做。

      否則,線程的名字和Throwable的棧蹤跡輸出到System.err上。

      參考書籍: Core Java, Volume II - Advanced Features 7th Edition

      建議參考: Concurrent Programming in Java

      Java 多線程

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:怎么EXCEL表格某列里增加下拉選項
      下一篇:解密衣柜訂單軟件:提升衣柜店面訂單管理的利器
      相關文章
      亚洲综合另类小说色区| 日韩亚洲人成网站| 亚洲av日韩片在线观看| 国产色在线|亚洲| 久久亚洲最大成人网4438| 亚洲中文无码a∨在线观看| 亚洲天堂福利视频| 亚洲伊人久久大香线蕉影院| 亚洲第一永久在线观看| 亚洲欧洲精品久久| 亚洲国产成人久久77| 亚洲系列国产精品制服丝袜第| 色拍自拍亚洲综合图区| 亚洲高清不卡视频| 91亚洲视频在线观看| 亚洲人配人种jizz| 成人亚洲国产va天堂| 亚洲丰满熟女一区二区哦| 久久久亚洲精华液精华液精华液 | 亚洲精品视频免费在线观看| 亚洲精品美女久久久久9999| 亚洲国产午夜精品理论片| 亚洲日本乱码一区二区在线二产线| 精品亚洲aⅴ在线观看| 亚洲国产精品免费在线观看| 国产精品亚洲四区在线观看| 亚洲精品理论电影在线观看| 亚洲成a人一区二区三区| 浮力影院亚洲国产第一页| 亚洲av日韩av天堂影片精品| 亚洲黄色中文字幕| 中文字幕亚洲综合小综合在线| 亚洲爆乳大丰满无码专区| 亚洲成AV人在线观看网址| 亚洲中文字幕无码不卡电影| 亚洲a在线视频视频| 亚洲导航深夜福利| 亚洲6080yy久久无码产自国产| 亚洲精品乱码久久久久久蜜桃| 亚洲精品乱码久久久久久自慰| 亚洲国产天堂在线观看|