線程池的單例實現


懶漢式

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolService {
    private static final int DEFAULT_CORE_SIZE=100;
    private static final int MAX_QUEUE_SIZE=500;
    private volatile static ThreadPoolExecutor executor; 

    private ThreadPoolService() {}; 

    // 獲取單例的線程池對象
    public static ThreadPoolExecutor getInstance() {
        if (executor == null) {
            synchronized (ThreadPoolService.class) {
                if (executor == null) {
                    executor = new ThreadPoolExecutor(DEFAULT_CORE_SIZE,// 核心線程數
                    MAX_QUEUE_SIZE, // 最大線程數
                    Integer.MAX_VALUE, // 閑置線程存活時間
                    TimeUnit.MILLISECONDS,// 時間單位
                    new LinkedBlockingDeque<Runnable>(Integer.MAX_VALUE),// 線程隊列
                    Executors.defaultThreadFactory()// 線程工廠
                    );
                }
            }
        }
        return executor;
    }

    public void execute(Runnable runnable) {
        if (runnable == null) {
            return;
        }
        executor.execute(runnable);
    }

    // 從線程隊列中移除對象
    public void cancel(Runnable runnable) {
        if (executor != null) {
            executor.getQueue().remove(runnable);
        }
    }
    
}

靜態參數(餓漢式)

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.*;

/**
 * 異步任務處理器
 */
public class AsyncTaskExecutor {

    /** 線程池保持ALIVE狀態線程數 */
    public static final int                 CORE_POOL_SIZE      = 10;

    /** 線程池最大線程數 */
    public static final int                 MAX_POOL_SIZE       = 40;

    /** 空閑線程回收時間 */
    public static final int                 KEEP_ALIVE_TIME     = 1000;

    /** 線程池等待隊列 */
    public static final int                 BLOCKING_QUEUE_SIZE = 1000;

    /** 業務請求異步處理線程池 */
    private static final ThreadPoolExecutor processExecutor = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.MICROSECONDS,
            new LinkedBlockingQueue<Runnable>(BLOCKING_QUEUE_SIZE),
       new TreadFactoryBuilder.setNameFormat("boomoom-thread-pool-%d").build(),
       new TreadPoolExecutor.DiscardPolicy());

    private AsyncTaskExecutor() {}; 

    /**
     * 異步任務處理
     *
     * @param task 任務
     */
    public void execute(Runnable task) {
        processExecutor.submit(task);
    }

}

在項目中,以上兩種方式都使用過,主要看線程任務在項目里的位置。采用第二種的,項目的主要業務就是異步線程來實現。

比較:餓漢式是線程安全的,在類創建的同時就已經創建好一個靜態的對象供系統使用,以后不再改變。
懶漢式如果在創建實例對象時不加上synchronized則會導致對對象的訪問不是線程安全的,推薦使用第一種。
從實現方式來講他們最大的區別就是懶漢式是延時加載,
懶漢式是在需要的時候才創建對象,而餓漢式在虛擬機啟動的時候就會創建。

餓漢式無需關注多線程問題、寫法簡單明了、能用則用。但是它是加載類時創建實例、所以如果是一個工廠模式、緩存了很多實例、那么就得考慮效率問題,因為這個類一加載則把所有實例不管用不用一塊創建。
懶漢式的優點是延時加載、缺點是應該用同步(比如double-check)、其實也可以不用同步、看你的需求了,多創建一兩個無引用的廢對象其實也沒什么大不了。

 

實踐:

    @Test
    public void threadPool() {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        Date startDate = new Date();
        System.out.println("開始時間:"+sf.format(startDate));
        for(int i=0;i<300000;i++){
            System.out.println("i=" + i);
            //啟動線程
            ThreadPoolService.getInstance().execute(() -> {
                int total = 0;
                for(int k=0;k<1000;k++){
                    total = total + k;
                }
                System.out.println("total=" + total);
            });
        System.out.println("結束了");
        Date endDate = new Date();
        System.out.println("結束時間:"+sf.format(endDate));
        System.out.println("耗時,單位秒:"+ (endDate.getTime()-startDate.getTime())/1000);
      }
}

運行結果:

 

 程序可以正常關閉

 

 

參考原文地址:https://www.cnblogs.com/boomoom/p/9290311.html


免責聲明!

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



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