本文以通俗易懂的范例入手,由淺入深的全面介紹了Java里的線(xiàn)程概念與線(xiàn)程同步技術(shù)。線(xiàn)程的創(chuàng)建
創(chuàng)
建新執(zhí)行線(xiàn)程有兩種方法。方法一種方法是將類(lèi)聲明為 Thread 的子類(lèi)。該子類(lèi)應(yīng)重寫(xiě) Thread 類(lèi)的 run 方法。事實(shí)上類(lèi)Thread本身也實(shí)現(xiàn)了接口Runnable,所以我們可以同過(guò)繼承Thread類(lèi)實(shí)現(xiàn)線(xiàn)程體。 參考:SellBookThread.java 與 CallSellBook.java 另 一種方法是聲明實(shí)現(xiàn) Runnable 接口的類(lèi)。該類(lèi)然后實(shí)現(xiàn) run 方法。 參考:SellBookRunnable.java 與 CallSellBook.java 線(xiàn)程的狀態(tài)
線(xiàn)程有四種狀態(tài):創(chuàng)建狀態(tài)(New),可運(yùn)行狀態(tài)(Runnable),阻塞狀態(tài)(Blocked),死亡狀態(tài)(Dead)。創(chuàng)建狀態(tài) (New): 當(dāng)執(zhí)行完 Thread t1 = new SellBookThread("SaleMan1", bookList); 語(yǔ)句之后,則t1處于創(chuàng)建狀態(tài)(New)。此時(shí)t1并未真正運(yùn)行。 可運(yùn)行狀態(tài)(Runnable): 當(dāng)Thread t1被創(chuàng)建,并執(zhí)行完 t1.start(); 語(yǔ)句之后,t1就處于可運(yùn)行狀態(tài)(Runnable)。此時(shí),系統(tǒng)為線(xiàn)程t1分配其所需的系統(tǒng)資源。并對(duì)t1加以調(diào)用(或者根據(jù)任務(wù)調(diào)度情況準(zhǔn)備調(diào)用)。 阻塞狀態(tài)(Blocked): 由于以下原因: 1) 調(diào)用了sleep()方法; 2) 調(diào)用了suspend()方法(該方法已不推薦使用); 3) 為等待條件鎖,調(diào)用wait()方法等; 4) 輸入輸出,或消息發(fā)生阻塞; 使 得線(xiàn)程處于阻塞狀態(tài)(Blocked)。處于該狀態(tài)的線(xiàn)程即使處理器空閑,也不會(huì)得到執(zhí)行。 死亡狀態(tài)(Dead): 死亡狀態(tài) (Dead)可以為自然死亡(線(xiàn)程運(yùn)行完畢),或者調(diào)用了stop()方法(該方法已不推薦使用)。 線(xiàn)程的優(yōu)先級(jí):
可以通過(guò)
Thread類(lèi)的 void setPriority(int newPriority) 方法為線(xiàn)程設(shè)置優(yōu)先級(jí)。但是不能保證高優(yōu) 先級(jí)的線(xiàn)程就會(huì)被先運(yùn)行。 線(xiàn)程組:
可以通過(guò)ThreadGroup group = new ThreadGroup(groupName); Thread t1 = new Thread(ThreadGroup g, Runnable r1); Thread t1 = new Thread(ThreadGroup g, Runnable r2); 等 方法把多個(gè)線(xiàn)程加到一個(gè)線(xiàn)程組里去,這樣可以通過(guò)ThreadGroup對(duì)這些線(xiàn)程進(jìn)行某些統(tǒng)一操作, 例 如:group.interrupt();中斷該組所有線(xiàn)程。 線(xiàn)程unchecked異常處理器:
可以通過(guò):public void static Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler) 方 法為所有線(xiàn)程指定一個(gè)unchecked異常處理器,該處理器必須實(shí)現(xiàn)UncaughtExceptionHandler接口。 線(xiàn)程同步:
線(xiàn)程同步指多個(gè)線(xiàn)程
同時(shí)訪(fǎng)問(wèn)某資源時(shí),采用一系列的機(jī)制以保證同時(shí)最多只能一個(gè)線(xiàn)程訪(fǎng)問(wèn)該資源。線(xiàn)程同步是多線(xiàn)程中必須考慮和解決的問(wèn)題,因?yàn)楹芸赡馨l(fā)生多個(gè)線(xiàn)程同 時(shí)訪(fǎng)問(wèn)(主要是寫(xiě)操作)同一資源,如果不進(jìn)行線(xiàn)程同步,很可能會(huì)引起數(shù)據(jù)混亂,造成線(xiàn)程死鎖等問(wèn)題。 使用synchronized同步線(xiàn) 程。 在J2SE5.0之前,只能使用synchronized來(lái)同步線(xiàn)程??梢允褂胹ynchronized來(lái)同步代碼塊或者方法。 同步 代碼塊例: synchronized(欲同步的對(duì)象obj) {需要同步的代碼塊}可以同步代碼塊。 參考:SellBookThread.java
該例synchronized (book) 表示若多個(gè)線(xiàn)程同時(shí)訪(fǎng)問(wèn)時(shí),只讓其中一個(gè)線(xiàn)程最先取得book對(duì)象,其它線(xiàn)程則阻塞直到代碼塊執(zhí)行完畢book對(duì)象被釋放后,其它線(xiàn)程才能取得該book 對(duì)象繼續(xù)執(zhí)行。 很多情況下,可以使用synchronized (this){...}來(lái)同步代碼塊。但需要注意的是,使用this作為同步對(duì)象的話(huà),如果同一個(gè)類(lèi)中存在多個(gè)synchronized (this){...}代碼塊,其中任何一個(gè)synchronized(this)代碼塊處于被執(zhí)行狀態(tài),則其它線(xiàn)程對(duì)其他 synchronized(this)代碼塊的訪(fǎng)問(wèn)也會(huì)受到阻塞。 同步方法例:
這種方法其實(shí)相當(dāng)于
由于默認(rèn)采用this作為同步對(duì)象,所以當(dāng)一個(gè)類(lèi)中有多個(gè)synchronized方法時(shí),同樣會(huì)存在以上問(wèn)題:即如果 有一個(gè)線(xiàn)程訪(fǎng)問(wèn)其中某個(gè)synchronized方法時(shí),直到該方法執(zhí)行完畢,其它線(xiàn)程對(duì)其它synchronized方法的訪(fǎng)問(wèn)也將受到阻塞。 有 關(guān)synchronized詳細(xì)說(shuō)明我們將在其它文章中加以說(shuō)明。 使用 java.util.concurrent.locks.ReentrantLock和 java.util.concurrent.locks.ReentrantReadWriteLock類(lèi)同步線(xiàn)程。 J2SE5.0加入了 ReentrantLock和ReentrantReadWriteLock可以對(duì)線(xiàn)程進(jìn)行同步,這里舉一個(gè)最簡(jiǎn)單的例子對(duì)其加以說(shuō)明:
其它J2SE5.0新導(dǎo)入的有關(guān)線(xiàn)程的相關(guān)接口/類(lèi):
java.util.concurrent.FutureFuture 接口可以保持/取得異步執(zhí)行的結(jié)果值 java.util.concurrent.Callable 類(lèi)似于Runnable接口。 但Runnable不能返回值,也不能拋出checked異常 java.util.concurrent.ExecutorService 該 接口繼承了Executor接口??梢酝ㄟ^(guò)submit方法把Runnable,Callable對(duì)象轉(zhuǎn)換為Future 形式。 java.util.concurrent.FutureTask 該 類(lèi)實(shí)現(xiàn)了Runnable和Future接口。提供異步執(zhí)行的取消以及異步執(zhí)行結(jié)果的取得等功能。 java.util.concurrent.Executor 執(zhí) 行指定的Runnable對(duì)象 java.util.concurrent.Executors 工具類(lèi)。提供靜態(tài)方法可以創(chuàng)建 Executor,ExecutorService,Callable等對(duì)象??梢酝ㄟ^(guò)newCachedThreadPool()等方法簡(jiǎn)單創(chuàng)建線(xiàn)程 池。 |
|
|
來(lái)自: 汲取者 > 《我的圖書(shū)館》