線程池一(創建線程池的兩種方式)


線程池,其實就是一個容納多個線程的容器,其中的線程可以反復使用,省去了頻繁創建線程對象的操作,

無需反復創建線程而消耗過多資源。

我們詳細的解釋一下為什么要使用線程池?

在java中,如果每個請求到達就創建一個新線程,開銷是相當大的。在實際使用中,創建和銷毀線程花費的時間和消耗的系統資源都相當大,

甚至可能要比在處理實際的用戶請求的時間和資源要多的多。除了創建和銷毀線程的開銷之外,活動的線程也需要消耗系統資源。

如果在一個jvm里創建太多的線程,可能會使系統由於過度消耗內存或“切換過度”而導致系統資源不足。為了防止資源不足,

需要采取一些辦法來限制任何給定時刻處理的請求數目,盡可能減少創建和銷毀線程的次數,特別是一些資源耗費比較大的線程的創建和銷毀,

盡量利用已有對象來進行服務。

線程池主要用來解決線程生命周期開銷問題和資源不足問題。通過對多個任務重復使用線程,線程創建的開銷就被分攤到了多個任務上了,

而且由於在請求到達時線程已經存在,所以消除了線程創建所帶來的延遲。這樣,就可以立即為請求服務,使用應用程序響應更快。另外,

通過適當的調整線程中的線程數目可以防止出現資源不足的情況。

2.1 使用線程池方式--Runnable接口

通常,線程池都是通過線程池工廠創建,再調用線程池中的方法獲取線程,再通過線程去執行任務方法。

l  Executors:線程池創建工廠類

n  public static ExecutorService newFixedThreadPool(int nThreads):返回線程池對象

l  ExecutorService:線程池類

n  Future<?> submit(Runnable task):獲取線程池中的某一個線程對象,並執行

l  Future接口:用來記錄線程任務執行完畢后產生的結果。線程池創建與使用

l  使用線程池中線程對象的步驟:

n  創建線程池對象

n  創建Runnable接口子類對象

n  提交Runnable接口子類對象

n  關閉線程池

代碼演示:
public class ThreadPoolDemo {
    public static void main(String[] args) {
        //創建線程池對象
        ExecutorService service = Executors.newFixedThreadPool(2);//包含2個線程對象
        //創建Runnable實例對象
        MyRunnable r = new MyRunnable();
        
        //自己創建線程對象的方式
        //Thread t = new Thread(r);
        //t.start(); ---> 調用MyRunnable中的run()
        
        //從線程池中獲取線程對象,然后調用MyRunnable中的run()
        service.submit(r);
        //再獲取個線程對象,調用MyRunnable中的run()
        service.submit(r);
        service.submit(r);
//注意:submit方法調用結束后,程序並不終止,是因為線程池控制了線程的關閉。將使用完的線程又歸還到了線程池中

//關閉線程池
        //service.shutdown();
    }
}
    Runnable接口實現類
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("我要一個教練");
        
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("教練來了: " +Thread.currentThread().getName());
        System.out.println("教我游泳,交完后,教練回到了游泳池");
    }
}

2.2 使用線程池方式—Callable接口

l  Callable接口:

與Runnable接口功能相似,用來指定線程的任務。其中的call()方法,用來返回線程任務執行完畢后的結果,call方法可拋出異常。

l  ExecutorService:線程池類

n  <T> Future<T> submit(Callable<T> task):獲取線程池中的某一個線程對象,並執行線程中的call()方法

l  Future接口:用來記錄線程任務執行完畢后產生的結果。線程池創建與使用

l  使用線程池中線程對象的步驟:

n  創建線程池對象

n  創建Callable接口子類對象

n  提交Callable接口子類對象

n  關閉線程池

代碼演示:
public class ThreadPoolDemo {
    public static void main(String[] args) {
        //創建線程池對象
        ExecutorService service = Executors.newFixedThreadPool(2);//包含2個線程對象
        //創建Callable對象
        MyCallable c = new MyCallable();
        
        //從線程池中獲取線程對象,然后調用MyRunnable中的run()
        service.submit(c);
        
        //再獲取個教練
        service.submit(c);
        service.submit(c);
//注意:submit方法調用結束后,程序並不終止,是因為線程池控制了線程的關閉。將使用完的線程又歸還到了線程池中

//關閉線程池
        //service.shutdown();
    }
}
    Callable接口實現類,call方法可拋出異常、返回線程任務執行完畢后的結果
public class MyCallable implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("我要一個教練:call");
        Thread.sleep(2000);
        System.out.println("教練來了: " +Thread.currentThread().getName());
        System.out.println("教我游泳,交完后,教練回到了游泳池");
        return null;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM