
一、操作系統中線程和進程的概念
現在的操作系統是多任務操作系統。多線程是實現多任務的一種方式。進程是指一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啟動多個線程。比如在Windows系統中,一個運行的exe就是一個進程。線程是指進程中的一個執行流程,一個進程中可以運行多個線程。比如java.exe進程中可以運行很多線程。線程總是屬于某個進程,進程中的多個線程共享進程的內存。同時”執行是人的感覺,在線程之間實際上輪換執行。
二、Java中的線程
在Java中,“線程”指兩件不同的事情:、java.lang.Thread類的一個實例;2、線程的執行。使用java.lang.Thread類或者java.lang.Runnable接口編寫代碼來定義、實例化和啟動新線程。一個Thread類實例只是一個對象,像Java中的任何其他對象一樣,具有變量和方法,生死于堆上。Java中,每個線程都有一個調用棧,即使不在程序中創建任何新的線程,線程也在后臺運行著。一個Java應用總是從main()方法開始運行,mian()方法運行在一個線程內,它被稱為主線程。一旦創建一個新的線程,就產生一個新的調用棧。線程總體分兩類:用戶線程和守候線程。當所有用戶線程執行完畢的時候,JVM自動關閉。但是守候線程卻不獨立于JVM,守候線程一般是由操作系統或者用戶自己創建的。
Java線程:概念與原理
一、多線程的好處是什么
(1)多線程技術使程序的響應速度更快 ,因為用戶界面可以在進行其它工作的同時一直處于活動狀態;
(2)當前沒有進行處理的任務時可以將處理器時間讓給其它任務;
(3)占用大量處理時間的任務可以定期將處理器時間讓給其它任務;
(4)可以隨時停止任務;
(5)可以分別設置各個任務的優先級以優化性能。
二、什么時候使用多線程技術
(1)耗時或大量占用處理器的任務阻塞用戶界面操作;
(2)各個任務必須等待外部資源 (如遠程文件或 Internet連接)。
三、多線程的缺點是什么
(1)等候使用共享資源時造成程序的運行速度變慢。這些共享資源主要是獨占性的資源 ,如打印機等。
(2)對線程進行管理要求額外的 CPU開銷。線程的使用會給系統帶來上下文切換的額外負擔。當這種負擔超過一定程度時,多線程的特點主要表現在其缺點上,比如用獨立的線程來更新數組內每個元素。
(3)線程的死鎖。即較長時間的等待或資源競爭以及死鎖等多線程癥狀。
(4)對公有變量的同時讀或寫。當多個線程需要對公有變量進行寫操作時,后一個線程往往會修改掉前一個線程存放的數據,從而使前一個線程的參數被修改;另外 ,當公用變量的讀寫操作是非原子性時,在不同的機器上,中斷時間的不確定性,會導致數據在一個線程內的操作產生錯誤,從而產生莫名其妙的錯誤,而這種錯誤是程序員無法預知的。
Java線程:創建與啟動
一、定義線程
1、擴展java.lang.Thread類。
2、實現java.lang.Runnable接口。
二、實例化線程
1、如果是擴展java.lang.Thread類的線程,則直接new即可。
2、如果是實現了java.lang.Runnable接口的類,則用Thread的構造方法。
三、啟動線程
在線程的Thread對象上調用start()方法,而不是run()或者別的方法。
在調用start()方法之前:線程處于新狀態中,新狀態指有一個Thread對象,但還沒有一個真正的線程。
在調用start()方法之后:發生了一系列復雜的事情
啟動新的執行線程(具有新的調用棧);
該線程從新狀態轉移到可運行狀態;
當該線程獲得機會執行時,其目標run()方法將運行。
注意:對Java來說,run()方法沒有任何特別之處。像main()方法一樣,它只是新線程知道調用的方法名稱(和簽名)。因此,在Runnable上或者Thread上調用run方法是合法的。但并不啟動新的線程。
Java線程:線程棧模型
線程棧是指某時刻時內存中線程調度的棧信息,當前調用的方法總是位于棧頂。線程棧的內容是隨著程序的運行動態變化的,因此研究線程棧必須選擇一個運行的時刻(實際上指代碼運行到什么地方)。
Java線程:線程狀態的轉換
一、線程狀態
線程的狀態轉換是線程控制的基礎。線程狀態總的可分為五大狀態,分別是:
二、阻止線程執行
我們只考慮三種狀態,分別是哪三種呢?
1、睡眠
Thread.sleep(longmillis)和Thread.sleep(long millis, int nanos)靜態方法強制當前正在執行的線程休眠(暫停執行),以“減慢線程”。當線程睡眠時,它入睡在某個地方,在蘇醒之前不會返回到可運行狀態。當睡眠時間到期,則返回到可運行狀態。
線程睡眠的原因:線程執行太快,或者需要強制進入下一輪,因為Java規范不保證合理的輪換。
注意:
1、線程睡眠是幫助所有線程獲得運行機會的最好方法。
2、線程睡眠到期自動蘇醒,并返回到可運行狀態,不是運行狀態。sleep()中指定的時間是線程不會運行的最短時間。因此,sleep()方法不能保證該線程睡眠到期后就開始執行。
3、sleep()是靜態方法,只能控制當前正在運行的線程。
4、線程的優先級和線程讓步yield()
線程的讓步是通過Thread.yield()來實現的。yield()方法的作用是:暫停當前正在執行的線程對象,并執行其他線程。
要理解yield(),必須了解線程的優先級的概念。線程總是存在優先級,優先級范圍在1~10之間。JVM線程調度程序是基于優先級的搶先調度機制。在大多數情況下,當前運行的線程優先級將大于或等于線程池中任何線程的優先級。但這僅僅是大多數情況。
注意:當設計多線程應用程序的時候,一定不要依賴于線程的優先級。因為線程調度優先級操作是沒有保障的,只能把線程優先級作用作為一種提高程序效率的方法,但是要保證程序不依賴這種操作。
當線程池中線程都具有相同的優先級,調度程序的JVM實現自由選擇它喜歡的線程。這時候調度程序的操作有兩種可能:一是選擇一個線程運行,直到它阻塞或者運行完成為止。二是時間分片,為池內的每個線程提供均等的運行機會。
設置線程的優先級:線程默認的優先級是創建它的執行線程的優先級。可以通過setPRiority(intnewPriority)更改線程的優先級。 線程優先級為1~10之間的正整數,JVM從不會改變一個線程的優先級。然而,1~10之間的值是沒有保證的。一些JVM可能不能識別10個不同的值,而將這些優先級進行每兩個或多個合并,變成少于10個的優先級,則兩個或多個優先級的線程可能被映射為一個優先級。
3、Thread.yield()方法
Thread.yield()方法作用是:暫停當前正在執行的線程對象,并執行其他線程。
yield()應該做的是讓當前運行線程回到可運行狀態,以允許具有相同優先級的其他線程獲得運行機會。因此,使用yield()的目的是讓相同優先級的線程之間能適當的輪轉執行。但是,實際中無法保證yield()達到讓步目的,因為讓步的線程還有可能被線程調度程序再次選中。
4、join()方法
Thread的非靜態方法join()讓一個線程B“加入”到另外一個線程A的尾部。在A執行完畢之前,B不能工作。
另外,join()方法還有帶超時限制的重載版本。例如t.join(5000);則讓線程等待5000毫秒,如果超過這個時間,則停止等待,變為可運行狀態。
線程的加入join()對線程棧導致的結果是線程棧發生了變化,當然這些變化都是瞬時的。