1. 程式人生 > >20165318 2017-2018-2 《Java程序設計》第八周學習總結

20165318 2017-2018-2 《Java程序設計》第八周學習總結

線程隊列 效果 成員變量 java應用程序 內存空間 產生 類名 lee ram

20165318 2017-2018-2 《Java程序設計》第八周學習總結

目錄

  • 學習過程遇到的問題及總結
  • 教材學習內容總結
    • 第12章 Java多線程機制
  • 代碼托管
  • 代碼統計

學習過程遇到的問題及總結

  • Q1:在運行課本代碼12_1時,結果如下:與課本上運行結果並不相同,再運行一次後發現,與上次結果竟然也不一樣。

技術分享圖片

  • 解決過程:在仔細看書後發現,書上解釋說,“該程序在不同的計算機運行或在同一臺計算機反復運行的結果不盡相同,輸出結果依賴當前CPU資源的使用情況”。

  • Q2:在本周的課堂測試中,我在編寫“計算壽命最長和最短國家”的時候,輸出結果中壽命最長的國家是正確的,但是壽命最短的國家卻一直不對:

技術分享圖片

  • 解決過程:經過反復糾正,我發現在有以下幾處錯誤:
    • 沒有去掉壽命記錄為空,即壽命為0的國家;
    • 將計算壽命最長和壽命最短的國家放到了兩個循環中,導致在計算壽命最長的國家時,已經讀到數據庫的底端了。
    • 將agemin賦值為0,導致數據庫中沒有壽命比0小的國家,將agemax賦值為100,沒有發現壽命比100大的國家。
      以下是正確的結果:

技術分享圖片

返回目錄

教材學習內容總結

第12章 Java多線程機制

12.1進程與進程

  • 程序是一段靜態的代碼,進程是程序的一次動態執行過程,這個過程也是進程本身從產生、發展至消亡的過程。

  • 線程不是進程,是比進程更小的執行單位。但與進程不同的是,線程的中斷和恢復可以更加節省系統的開銷。

  • 沒有進程就沒有線程。

12.2Java中的線程

1、Java的多線程機制
  • Java語言的一大特性點就是內置對多線程的支持。

  • 多線程是指一個應用程序中同時存在幾個執行本,按幾條不同的執行線索共同工作的情況。

  • 計算機在任何給定的時刻只能執行線程中的一個。Java虛擬機快速地把控制從一個線程切換到另一個線程,這些線程被輪流執行,使得每個線程都有機會使用CPU資源。

2、主線程(main線程)
  • 主線程(main線程)負責執行main方法。

  • 如果main方法中沒有創建其他的線程,那麽當main方法執行完最後一個語句,即main方法返回時,JVM就會結束Java應用程序。如果main方法中又創建了其他線程,那麽JVM就要在主線程和其他線程之間輪流切換,保證,每個線程都有機會使用CPU,main方法即使執行完最後的語句(主線程結束),JVM也不會結束Java應用程序,JVM一直要等到Java應用程序都結束之後,才結束Java應用程序。

3、線程的狀態和生命周期

Java語言使用Thread類及其子類的對象來表示線程。

新建的線程在一個完整的生命周期中通常要經歷以下4個狀態:

  • 新建:一個Thread類或其子類的對象被聲明並創建,已經有了相應的內存空間和其他資源。

  • 運行:JVM將CPU使用權切換給該線程時,此線程就可以脫離創建它的主線程獨立開始自己的生命周期了。
    如果線程是Thread的子類創建的,該類中的run()方法就立刻執行,且程序必須在子類中重寫父類的run()方法。
    在線程沒有結束run()方法之前,不要讓線程再調用start()方法,否則將發生IllegalThreadStateException異常。

  • 中斷:有四種原因的中斷
    • JVM將CPU資源從當前線程切換給其他線程,使本線程讓出CPU的使用權處於中斷狀態。
    • 線程使用CPU資源期間,執行了sleep(int millsecond)方法,使當前線程進入休眠狀態。
    • 執行了wait()方法,使得當前線程進入等待狀態,必須由其他線程調用notify()方法通知它,使得它重新進到線程隊列中排隊等待CPU資源。
    • 執行某個操作進入阻塞狀態,比如執行讀/寫操作引起阻塞。只有當引起阻塞的原因消除時,線程才重新進到線程隊列中排隊等待CPU資源。
  • 死亡:不具有繼續運行的能力。實質是線程釋放了實體,即釋放分配給線程對象的內存。
    • 死亡原因之一是執行完run()方法中的全部語句,結束了run()方法;
    • 死亡原因之二是強制run()方法結束。
4、線程調度與優先級
  • 每個Java線程的優先級都在常數1和10之間,即Thread.MIN_PRIORITYThread.MAX_PRIORITY之間。如果沒有明確地設置線程的優先級別,,每個線程的優先級都為常數5,即Thread.NORM_PRIORITY

  • 可以通過setPriority(int grade)方法調整優先級, getPriority 方法返回線程的優先級。

  • 當線程使用CPU資源的時間到時後,即使線程沒有完成自己的全部操作,JVM也會中斷當前線程的執行,把CPU的使用權切換給下一個排隊等待的線程,當前線程將等待CPU資源的下一次輪回,然後從中斷處繼續執行。

  • JVM的線程調度器的任務是使高優先級的線程能始終運行,一旦時間片有空閑,則使具有同等優先級的線程以輪流的方式順序使用時間片。

12.3Thread類與線程的創建

1、使用Thread的子類
  • 在編寫Thread類的子類時,需要重寫父類的run()方法。

  • 優點:可以在子類中增加新的成員變量,實現城具有某種屬性,也可以在子類中新增加方法,使線程具有某種功能。

  • Java不支持多繼承,Thread類的子類不能再擴展其他的類。

2、使用Thread類。
  • 用Thread類直接創建線程對象:Thread(Runnable target),該構造方法中的參數是一個Runnable類型的接口。
    在創建線程對象時必須向構造方法的參數傳遞一個實現Runnable接口類的實例,該實例對象稱作所創線程的目標對象,當線程調用start()方法後,一旦輪到它來享用CPU資源,目標對象就會自動調用接口中的run()方法(接口回調)

  • 對於使用同一目標對象的線程,目標對象的成員變量自然就是這些線程共享的數據單元,使用Runnable接口比使用Thread的子類更具有靈活性。

3、目標對象與線程的關系
  • 目標對象和線程完全解耦:目標對象經常需要通過獲得線程的名字(因為無法獲得線程對象的引用)以便確定被JVM正在執行的線程是哪個。

  • 目標對象組合線程(弱耦合):目標對象可以組合線程,目標對象類組合線程對象時,目標對象可以通過獲得線程對象的引用。

4、關於run方法啟動的次數
  • 對於具有相同目標對象的線程,當其中一個線程享用CPU資源時,目標對象自動調用接口中的run方法,這時,run方法中的局部變量被分配內存空間,當輪到另一個線程享用CPU資源時,目標對象會再次調用接口中的run方法,run()方法中的局部變量會再次分配內存空間。即run()方法已經啟動運行了兩次,分別運行在不同的線程中

12.4線程的常用方法

  • start() : 線程調用該方法將啟動線程,使之從新建狀態進入就緒隊列排隊,一旦輪到它來享用CPU資源時,就可以脫離創建它的線程獨立開始自己的生命周期了。

  • run(): Thread類的run()方法與Runnable接口中的run()方法的功能和作用相同,都用來定義線程對象被調度之後所執行的操作,都是系統自動調用而用戶程序不得引用的方法。

  • sleep(int millsecond): 優先級高的線程可以在它的run()方法中調用sleep方法來使自己放棄CPU資源,休眠一段時間。

  • isAlive(): 線程處於“新建”狀態時,線程調用isAlive()方法返回false。在線程的run()方法結束之前,即沒有進入死亡狀態之前,線程調用isAlive()方法返回true。

  • currentThread():
    該方法是Thread類中的類方法,可以用類名調用,該方法返回當前正在使用CPU資源的線程。

  • interrupt():
    一個占有CPU資源的線程可以讓休眠的線程調用interrupt()方法“吵醒”自己,即導致休眠的線程發生InterruptedException異常,從而結束休眠,重新排隊等待CPU資源。

12.5線程同步

  • 多個線程調用synchronized方法必須遵守同步機制。

  • 在處理線程同步時,要做的第一件事就是要把修改數據的方法用關鍵字synchronized來修飾。

  • 所謂線程同步就是若幹個線程都需要使用一個synchronized修飾的方法。

  • 線程同步機制:當一個線程A使用synchronized方法時,其他線程想使用這個synchronized方法時就必須等待,直到線程A使用完該synchronized方法。

12.6協調同步的線程

  • wait()方法可以中斷方法的執行,使本線程等待,暫時讓出CPU的使用權,並允許其它線程使用這個同步方法。

  • notifyAll()方法通知所有的由於使用這個同步方法而處於等待的線程結束等待。曾中斷的線程就會從剛才的中斷處繼續執行這個同步方法,並遵循“先中斷先繼續”的原則。

  • notify()方法只是通知處於等待中的線程的某一個結束等待。

  • wait()notify()notifyAll()都是Object類中的final方法,被所有的類繼承且不允許重寫得方法。不可以在非同步方法中使用wait()notify()notifyAll()

12.7線程聯合

  • 一個線程A在占有CPU資源期間,可以讓其它線程調用join()和本線程聯合,如:
    B.join();
    稱A在運行期間聯合了B。如果線程A在占有CPU資源期間一旦聯合B線程,那麽A線程將立刻中斷執行,一直等到它聯合的線程B執行完畢,A線程再重新排隊等待CPU資源,以便恢復執行。如果A準備聯合的B線程已經結束,那麽B.join()不會產生任何效果。

12.8GUI線程

  • 當Java程序包含圖形用戶界面(GUI)時,Java虛擬機在運行應用程序會自動
    啟動更多的線程

  • 兩個重要的線程
    • AWT-EventQuecue:負責處理GUI事件
    • AWT-Windows:負責將窗體或組件繪制到桌面

12.9計時器線程

  • 使用Timer類的方法start()啟動計時器,即啟動線程。

  • 使用Timer類的方法stop()停止計時器,即掛起線程。

  • 使用restart()重新啟動計時器,即恢復線程。

  • 使用Timer(int a,Object b)創建一個計時器,計時器每隔a毫秒“震鈴”一次,參數b是計時器的監視器。計時器發生的震鈴事件是ActinEvent類型事件。當震鈴事件發生時,監視器就會監視到這個事件,監視器就回調ActionListener接口中的actionPerformed(ActionEvent e)方法。

  • 註:計時器的監視器必須是組件類(例如JFrameJButton等)的子類的實例,否則計時器無法啟動。

12.10守護線程

  • 線程默認是非守護線程(即用戶(user)線程)。

  • 一個線程調用void setDaemon(boolean on)方法可以將自己設置成一個守護(Daemon)線程,例如:thread.setDaemon(true);

  • 當程序中的所有用戶線程都已結束運行時,即使守護線程的run方法中還有需要執行的語句,守護線程也立刻結束運行。

  • 用戶線程與守護線程的區別在於虛擬機的離開。如果用戶線程已經全部退出運行,只剩下守護線程存在,那麽虛擬機也就退出了。

  • 一個線程必須在運行前設置自己是否是守護線程。

返回目錄

代碼托管

碼雲鏈接

代碼統計

技術分享圖片

技術分享圖片

技術分享圖片

返回目錄

20165318 2017-2018-2 《Java程序設計》第八周學習總結