Java中多線程的實現方式html
在java的歷史版本中,有兩種建立多線程程序的方法java
1) 經過建立Thread類的子類來實現(Thread類提供了主線程調用其它線程並行運行的機制)緩存
主要步驟:多線程
自定義類繼承Thread類,而後覆蓋其中的run方法,使得該線程可以完成特定的工做,使用start方法啓動線程,將執行權轉交到run.框架
2) 經過實現Runable接口的類來實現(推薦,能夠實現數據共享,並且能夠避免由於類單繼承的侷限)異步
主要步驟:ide
a>. 建立某個類實現Runnable接口,實現run()方法。性能
b>. 建立Thread對象,用實現Runnable接口的對象做爲參數實例化該Thread對象。優化
c>. 調用Thread的start方法。spa
說明:
Thread是一個類,而Runnable是一個接口.
JAVA線程控制着程序執行的主路徑;當你用java命令調用JVM時,JVM建立了一個隱式線程來執行main方法.
3) 在JDK5.0後,使用Executor框架管理線程.
雖然可使用Thread類來顯示的建立線程,但推薦的作法是使用Executor接口,讓它來管理Runnable對象的執行.
一般Executor對象會建立並管理一組執行Runnable對象的線程,這組線程被稱爲線程池,Executor基於生產者-消費者模式.提交任務的執行者是生產者(產生待完成的工做單元),執行任務的線程是消費者(消耗掉這些工做單元)
採用Executor的優點
a) Executor對象可以複用已有的線程,從而消除了爲每一個任務建立新線程的開銷,
b) 它能經過優化線程的數量,提升程序性能,保證處理器一直處於忙碌狀,而沒必要建立過多的線程使程序資源耗盡。
Executor接口的定義[JDK源碼引入]
public interface Executor{ void execute(Runnable command); }
ExecutorService接口[JDK源碼引入]
public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
ExecutorService暗示了生命週期的3種狀態:運行(running)、關閉(shutting down)和終止(terminated).
ExecutorService最初建立後的初始狀態是運行狀態.shutdown方法會啓動一個平緩的關閉過程:中止接受新的任務,同時等待已經提交的任務完成-包括還沒有開始執行的任務. shutdownNow方法會啓動一個強制關閉過程,嘗試取消全部運行中的任務和排在隊列中還沒有開始的任務.在關閉後提交到ExecutorService的任務會拋出RejectedExecution異常.
Executors類,該類是一個獨立類,提供一系列靈活的線程池實現和一些有用的預設配置.[JDK源碼引入]
public class Executors { public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<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類。
新線程實例應用
使用新線程實現一個無返回的線程實例
public class ThreadPoolTest { public static void main(String[] args) { //使用動態緩存線程池,池中的線程隨着任務數量的變化而變化
ExecutorService threadPool = Executors.newCachedThreadPool(); //循環產生5個任務丟給線程池
for(int i=1; i<=5; i++){ final int taskNum = i; threadPool.execute(new Runnable() { @Override public void run() { for(int j=1; j<=2; j++){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("任務[" + taskNum + "]使用線程[" + Thread.currentThread().getName() + "]循環打印數據:" + j); } } });//end execute(..);
}//end for(var i) //若是線程中任務執行完畢,沒有任務須要執行了,就關閉線程池,若是不關閉,程序就不會結束,而是持續等待新的任務.
threadPool.shutdown(); } }
傳統的實現方式以及上面的線程實現方式都不可能有返回值.在ExecutorService中定義了系列的submit(xxx)方法,該方法能夠返回Future<V>接口,經過調用其V get() throws InterruptedException, ExecutionException;就能夠獲取到線程執行結果.submit能夠傳滴一個Runnable接口的實現類,也能夠傳遞一個Callable接口的實現類.
Callable接口的實現類[JDK源碼引入]
public interface Callable<V> { V call() throws Exception; }
說明:Future<V>表明一個異步執行的操做,經過get()方法能夠得到操做的結果,若是異步操做尚未完成,則get()會使當前線程阻塞,直到計算完成.
編寫5.0新線程的步驟
1.先寫一個Callable的子類,而後實現call()方法.
2.調用Executors.newXXThreadPool()返回ExecutorService類型.
3.調用ExecutorService中的submit(Callable的子類)方法啓動線程.
4.只有調用ExecutorService的shutdown()方法才能真正的離開虛擬機.
import java.util.concurrent.*; public class ExecutorTest implements Callable { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { //建立緩存線程池
ExecutorService pool = Executors.newCachedThreadPool(); //指定線程,獲取線程返回結果
Future returnV = pool.submit(new ExecutorTest()); //獲取線程返回結果
System.out.println("" + returnV.get().toString()); //關閉線程池
pool.shutdown(); } @Override public Object call() throws Exception { for(int i=1; i<=5; i++){ Thread.sleep (500); System.out .println(Thread.currentThread().getName()+" print value " +i); } return "Multiple Thread Implements Callable"; } }
該接口擴展了Executor接口,並聲明瞭許多方法用於管理Executor的聲明週期