Java四種線程池


線程池的好處

1、線程的創建需要消耗的,用完了馬上就扔了比較可惜,所以把它緩存起來,以后還能再用;

2、可以根據實際情況調整線程池的大小,防止線程太多;

3、有些場合可以用線程池來做同步(比如多個線程使用同一文件系統時,可以用SingleThreadExecutor來保持同步);

可緩存(可變大小)的線程池 CachedThreadPool

這是一種很寬松的線程池,當任務來了之后,如果沒有可用的線程那么就新建一個,如果有空閑的線程,則直接使用現有的線程。

可以根據實際的處理需求動態變化線程的數量。如果實際處理需求沒那么多了,就會把部分線程回收掉。反之,如果實際處理需求又上來了,就會重新創建線程。

比如下面的代碼,模擬每隔2秒才有一個新任務,而這個任務每次只需要1秒就能執行完:

public class CachedThreadPool {
    
    static Random random = new Random();
    static int taskId = 0;
    static ExecutorService service = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        while(true) {
            service.execute(new MyThread());
            try {
                //新增任務速度
                Thread.sleep(new Long(2*1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    static class MyThread implements Runnable{
        @Override
        public void run() {
            System.out.println("thread " + Thread.currentThread().getName() + " is running for task:" + (taskId++));
            try {
                //任務線程執行所需時間
                Thread.sleep(new Long(1*1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
}

這種情況下,線程池只需要一個線程就夠用了:

thread pool-1-thread-1 is running for task:0
thread pool-1-thread-1 is running for task:1
thread pool-1-thread-1 is running for task:2
thread pool-1-thread-1 is running for task:3
thread pool-1-thread-1 is running for task:4
thread pool-1-thread-1 is running for task:5

如果把任務執行時間增加到3秒,則會產生3個線程:

thread pool-1-thread-1 is running for task:0
thread pool-1-thread-2 is running for task:1
thread pool-1-thread-3 is running for task:2
thread pool-1-thread-1 is running for task:3
thread pool-1-thread-2 is running for task:4
thread pool-1-thread-3 is running for task:5
thread pool-1-thread-1 is running for task:6
thread pool-1-thread-2 is running for task:7
thread pool-1-thread-3 is running for task:8
thread pool-1-thread-1 is running for task:9

如果剛開始新增任務速度很快,后來變慢了,之前新增的線程會被回收掉

public static void main(String[] args) {
        int i = 0;
        while(true) {
            service.execute(new MyThread());
            long sleep = i>=5 ? 2000 : 50;   #<---------------- 前五個任務新增得很快故意讓線程池多創建任務,之后變慢,讓增加速度比任務執行速度還慢
            try {
                //新增任務速度
                Thread.sleep(sleep);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i++;
        }
    }
    
    static class MyThread implements Runnable{
        @Override
        public void run() {
            System.out.println("thread " + Thread.currentThread().getName() + " is running for task:" + (taskId++));
            try {
                //任務線程執行所需時間
                Thread.sleep(new Long(1*1000));  #<-------------------- 執行速度是1秒,新增速度的一半
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

輸出結果如下:

thread pool-1-thread-1 is running for task:0
thread pool-1-thread-2 is running for task:1
thread pool-1-thread-3 is running for task:2
thread pool-1-thread-4 is running for task:3
thread pool-1-thread-5 is running for task:4
thread pool-1-thread-6 is running for task:5
thread pool-1-thread-6 is running for task:6
thread pool-1-thread-6 is running for task:7
thread pool-1-thread-6 is running for task:8
thread pool-1-thread-6 is running for task:9
thread pool-1-thread-6 is running for task:10
thread pool-1-thread-6 is running for task:11
thread pool-1-thread-6 is running for task:12
...

后面只有thread-6在跑了,打開jconsole,會發現其他的thread-1-threac-X已經不見了。

 

 

固定大小的線程池 FixedThreadPool

這個好理解了,我就這么幾個線程,你任務再多也沒用。

 

定時執行線程池 ScheduledThreadPool

定時任務線程池要注意的是,在線程資源稀缺的時候(就是線程數量設置的很小,比增加的定時任務還少,不夠用),任務的執行時間會影響任務的執行周期。簡單來說就是不要把線程數量設置的太少了。

單線程的線程池 SingleThreadExecutor

它創建單個工作者來執行任務,如果工作者線程異常退出了會重新創建一個來替換。它可以確保任務在隊列中依次串行執行,例如FIFO、LIFO、優先級。另外固定大小的線程池還提供了大量同步機制,從而是一個任務寫入到內存的結果對於后續的任務是可見的。


免責聲明!

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



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