一.進程與線程的區別
1.定義:
進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
2.關系:
一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以並發執行。
相對進程而言,線程是一個更加接近於執行體的概念,它可以與同進程中的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。
3.區別:
進程和線程的主要差別在於它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行並且又要共享某些變量的並發操作,只能用線程,不能用進程。
3.1線程的划分尺度小於進程,使得多線程程序的並發性高。
3.2簡而言之,一個程序至少有一個進程,一個進程至少有一個線程。
3.3另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
3.4線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
3.5從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
4.優缺點:
線程和進程在使用上各有優缺點:線程執行開銷小,但不利於資源的管理和保護;而進程正相反。同時,線程適合於在SMP機器上運行,而進程則可以跨機器遷移。
二.多線程兩個基本實現框架
Java編寫程序都運行在在Java虛擬機(JVM)中,在JVM的內部,程序的多任務是通過線程來實現的。每用Java命令啟動一個Java應用程序,就會啟動一個JVM進程。在同一個JVM進程中,有且只有一個進程,就是它自己。在這個JVM環境中,所有程序代碼的運行都是以線程來運行。
在Java中,多線程的實現有兩種基本方式:繼承java.lang.Thread類;實現java.lang.Runnable接口。(優先選擇)。
第三種方式(少):使用ExecutorService、Callable、Future實現有返回結果的多線程。
1.繼承Thread類來實現多線程
當一個類繼承Thread類時,在類中必須重載run()方法,同時這個run()方法也是線程的入口,在調用的過程中,通過調用start()方法來啟動新線程,其基本框架為:
一般生活場窗口售票情況:
這樣出現的問題是:1.不清楚線程之間執行的具體順序,2.相當於每個窗口都在售賣4張票。
優化方案:實現Runnable接口
2.實現Runnable接口來實現多線程
和繼承Thread類似,當一個類實現Runnable接口時,在類中也必須重載run()方法,同時這個run()方法也是線程的入口,在調用的過程中,通過調用start()方法來啟動新線程,其基本框架為:
代碼改進:
程序執行的結果為:
1 1號窗口正在賣票5 2 1號窗口正在賣票4 3 1號窗口正在賣票3 4 2號窗口正在賣票2 5 1號窗口正在賣票1
3.使用ExecutorService、Callable、Future實現有返回結果的多線程
ExecutorService、Callable、Future這個對象實際上都是屬於Executor框架中的功能類。返回結果的線程是在JDK1.5中引入的新特征,確實很實用,有了這種特征我就不需要再為了得到返回值而大費周折了,而且即便實現了也可能漏洞百出。可返回值的任務必須實現Callable接口,類似的,無返回值的任務必須Runnable接口。
代碼說明:
上述代碼中Executors類,提供了一系列工廠方法用於創先線程池,返回的線程池都實現了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
創建固定數目線程的線程池。
public static ExecutorService newCachedThreadPool()
創建一個可緩存的線程池,調用execute 將重用以前構造的線程(如果線程可用)。如果現有線程沒有可用的,則創建一個新線程並添加到池中。終止並從緩存中移除那些已有 60 秒鍾未被使用的線程。
public static ExecutorService newSingleThreadExecutor()
創建一個單線程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
創建一個支持定時及周期性的任務執行的線程池,多數情況下可用來替代Timer類。
ExecutoreService提供了submit()方法,傳遞一個Callable,或Runnable,返回Future。如果Executor后台線程池還沒有完成Callable的計算,這調用返回Future對象的get()方法,會阻塞直到計算完成。
二:補充說明
在繼承Thread類實現多線程時,我們創建了三個不同的對象,所以創建的三個線程實際上是完成的三個不同的任務,所以才會相互獨立的完成;而通過實現Runable接口來實現多線程時,我們只創建了一個對象,然后實例化三個不同的線程去完成這個任務,所以相當於是共同完成任務。
Thread類也是實現Runnable接口的:
Thread中的run方法其實就是調用的是Runnable接口的run方法。
Reference:http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html
