java線程概述

使用java線程方法有兩種

一是顯式的創建執行線程,創建執行線程有兩種方法

創建新執行線程有兩種方法。一種方法是將類聲明爲 Thread 的子類。該子類應重寫 Thread 類的 run 方法。接下來可以分配並啓動該子類的實例。例如,計算大於某一規定值的質數的線程可以寫成:
     class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }
         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }
 
然後,下列代碼會創建並啓動一個線程:
     PrimeThread p = new PrimeThread(143);
     p.start();
創建線程的另一種方法是聲明實現 Runnable 接口的類。該類然後實現 run 方法。然後可以分配該類的實例,在創建 Thread 時作爲一個參數來傳遞並啓動。採用這種風格的同一個例子如下所示:
     class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }
 
         public void run() {
             // compute primes larger than minPrime
              . . .
         }
     }

然後,下列代碼會創建並啓動一個線程:
     PrimeRun p = new PrimeRun(143);
     new Thread(p).start();
每個線程都有一個標識名,多個線程可以同名。如果線程創建時沒有指定標識名,就會爲其生成一個新名稱。

 一般不推薦使用第一種直接繼承Thread的方式,而是使用Runnable接口來創建線程

使用線程的第二個方法是採用線程池

線程相對與進程來誰說雖說代價小得多,但也需跟操作系統交互還是有一定代價的,特別是有時候一個新線程可能只需完成一個很小的任務執行很少的代碼,這樣的線程聲明週期比較短,還是有一定的開銷的,這時候就可以使用線程池。一個線程池中可有多個已經創建好隨時準備運行的空閒線程。將Runnable對象交給線程池,線程池其中的一個線程就負責運行這個Runnable的run方法。而當run方法運行完畢是線程不一定立即死亡,而是繼續等待下一次的服務。

使用線程池的另一個好處是可以控制同一進程中線程並行的數目。採用第一種方式顯式創建線程的話如果有10個就會有10個線程併發執行有100個就會有100個線程併發執行,如果1000個10000個那麼...虛擬機估計罷工了。採用線程池的話可以創建一個擁有最大線程數目的線程池,最多隻能併發執行固定數目的線程多出來的線程只能等待正在執行的線程退出。在java.util.concurrent包中有個類Executors,該類有以下五個靜態方法:

1.newCachedThreadPool():創建一個緩衝線程池,必要是創建新線程,線程執行任務後不馬上註銷,而是緩存60秒鐘,以便執行新的其他的任務。

2.newFixedThreadPool():創建一個固定數目的線程池(池裏總是有那麼多水,既不會蒸發也不會流入..),線程池總是會保持指定數目的線程而不管是否有線程空閒還是線程不夠,提交到線程池的任務太多的話多餘的只能等,這樣可以控制併發線程數目。

3.newSingleThreadPExecutor():創建只有一個線程的”線程池“(池裏只有一滴水啊),所有提交到此種線程池的任務都要排隊等待這個唯一的線程去執行。

4.newScheduledThreadPool():用於固定執行而構建的固定線程池,用於替代java.util.Timer

5.newSingleThreadScheduleExecutor():用於預定執行而構建的單線程池

上述五個方法都會返回一個實現了ExecutorService接口的ThreadPoolExecutor類的對象。向線程池提交任務的方法爲:將一個實現Runnable或Callable接口的對象提交給ExecutorService:

Future<?> submit(Runable task)

Future<T> submit(Runable task, T result)

Future<t> submit(Callable<T> task)

線程會在適當的時候儘早執行提交的任務,調用submit時會返回一個Future對象,用以查詢該任務的狀態,或者取消該任務。

第一個submit方法提交一個Runable對象返回一個Future<?>,可使用該對象調用isDone、cancel、或者isCancelled來查詢任務狀態。但是此Future對象的get方法在任務完成的時候知識簡單的返回null

第二個版本的submit方法同樣提交一個Runable對象,並且返回Future的get方法在任務完成的時候返回傳入的result對象

第三個submit方法提交一個Callable對象,並且返回的Future對象將在計算結構、準備好的時候得到它。

當想要註銷一個線程池,可調用shutdown方法,該方法啓動該線程池的關閉序列。此時線程池並不是馬上就壯烈犧牲了線程也沒了,而是等待所以任務都完成以後,線程池中的線程纔會死亡,被關閉的執行器不再接受新任務。也可以調用shutdownNow,此時線程池會取消正在排隊等待處理的任務並且試圖中斷正在執行的線程。

使用線程池的步驟如下:

1)調用Executors類中的靜態方法newCachedThreadPool或newFixedThreadPool,創建一個新的線程池並返回一個執行器對象ExecutorService(ThreadPoolExecutor)

2)調用執行器對象的submit提交Runnable或者Callable對象

3)如果想要取消一個任務,或如果提交Callable對象,那就要保存返回的Future對象

4)當不再提交任務任務時,調用shutdown

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章