Java線程的四種創建方式:
1 使用Thread子類創建和啟動線程
2 使用實現Runnable的實現類創建和啟動線程
3 使用Callable和FutureTask來創建異步任務,然后創建線程實例
4 通過線程池創建線程(JUC)
(1)向線程池提交任務的兩種方式:
方式一:使用execute方法(無返回值)
void execute(Runnable command);
方式二:使用submit方法(有返回值、可簡單管理線程,並且可以處理異常)
Future<?> submit(Runnable task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
(2)關閉線程池:
pool.shutdown();
4.1 Executors四個快捷創建線程池方法(不推薦)
4.1.1 newSingleThreadExecutor()創建單一線程池
(1)任務按照次序執行
(2)池中只有唯一線程,並且存活時間是無限的
(3)線程繁忙時,新任務會進入到阻塞隊列
場景:任務依次執行。
4.1.2 newFixedThreadPool(3)創建固定數量線程池
場景:處理CPU密集型的任務。在CPU被工作線程長時間使用的情況下,能確保盡可能少的分配線程。
弊端:內部使用無界隊列來存放任務,當任務超過線程池最大容量需要處理時,隊列無限增大,使服務器資源耗盡。
4.1.3 newCachedThreadPool()可緩存線程池
場景:快速處理突發性強、耗時較短的任務。
弊端:沒有最大線程池數量限制。
4.1.4 newScheduledThreadPool(2)可調度線程池
// 內含一個線程池
newSingleThreadScheduledThreadPool();
// 內含n個線程池
newScheduledThreadPool(int corePoolSize);
通過scheduleAtFixedRate方法提交任務:
ScheduledFuture<?> scheduleAtFixedRate(
Runnable command,
// 首次執行任務延遲時間
long initialDelay,
// 執行任務間隔時間
long period,
// 計時單位
TimeUnit unit);
場景:周期性執行任務場景。
4.2 創建標准線程池的方法(推薦)
快捷創建線程池的方法存在嚴重的性能問題,所以大部分企業都禁止使用快捷線程池,要求通過標准構造器ThreadPoolExecutor構造線程池。
// 標准構造器
public ThreadPoolExecutor(
// 核心線程數,即使線程空閑(idle),也不會回收
int corePoolSize,
// 線程數上限
int maximumPoolSize,
// 線程最大空閑(idle)時長
long keepAliveTime, TimeUnit unit,
// 任務的排隊隊列
BlockingQueue<Runnable> workQueue,
// 新線程的產生方式
ThreadFactory threadFactory,
// 拒絕策略
RejectedExecutionHandler handler)
