java 线程工厂_Java并发编程:Java的四种线程池的使用,以及自定义线程工厂
引言
通過(guò)前面的文章,我們學(xué)習(xí)了Executor框架中的核心類ThreadPoolExecutor ,對(duì)于線程池的核心調(diào)度機(jī)制有了一定的了解,并且成功使用ThreadPoolExecutor 創(chuàng)建了線程池。
而在Java中,除了ThreadPoolExecutor ,Executor框架中還提供了四種線程池,這四種線程池都是直接或間接配置ThreadPoolExecutor的參數(shù)實(shí)現(xiàn)的,對(duì)于ThreadPoolExecutor類不熟悉的讀者可以參考Java并發(fā)編程:Java線程池核心ThreadPoolExecutor的使用和原理分析
四種線程池
四種線程池分別是:newCachedThreadPool、newFixedThreadPool 、newScheduledThreadPool 和newSingleThreadExecutor ,下面對(duì)這幾個(gè)線程池一一講解。
newCachedThreadPool:可緩存的線程池
源碼:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
newCachedThreadPool的方法中是返回一個(gè)ThreadPoolExecutor實(shí)例,從源碼中可以看出該線程池的特點(diǎn):
1、該線程池的核心線程數(shù)量是0,線程的數(shù)量最高可以達(dá)到Integer 類型最大值;
2、創(chuàng)建ThreadPoolExecutor實(shí)例時(shí)傳過(guò)去的參數(shù)是一個(gè)SynchronousQueue實(shí)例,說(shuō)明在創(chuàng)建任務(wù)時(shí),若存在空閑線程就復(fù)用它,沒(méi)有的話再新建線程。
3、線程處于閑置狀態(tài)超過(guò)60s的話,就會(huì)被銷毀。
用法:
public static void main(String[] args) {
//定義ExecutorService實(shí)例
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//調(diào)用execute方法
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread() + ":" + index);
}
});
}
}
上面的代碼因?yàn)槊看窝h(huán)都是隔一秒執(zhí)行,這個(gè)時(shí)間足夠之前的線程工作完畢,并在新循環(huán)中復(fù)用這個(gè)線程,程序的運(yùn)行結(jié)果如下:
Thread[pool-1-thread-1,5,main]:0
Thread[pool-1-thread-1,5,main]:1
Thread[pool-1-thread-1,5,main]:2
Thread[pool-1-thread-1,5,main]:3
Thread[pool-1-thread-1,5,main]:4
Thread[pool-1-thread-1,5,main]:5
Thread[pool-1-thread-1,5,main]:6
Thread[pool-1-thread-1,5,main]:7
Thread[pool-1-thread-1,5,main]:8
Thread[pool-1-thread-1,5,main]:9
newFixedThreadPool:定長(zhǎng)線程池
源碼:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
線程池特點(diǎn):
1、線程池的最大線程數(shù)等于核心線程數(shù),并且線程池的線程不會(huì)因?yàn)殚e置超時(shí)被銷毀。
2、使用的列隊(duì)是LinkedBlockingQueue,表示如果當(dāng)前線程數(shù)小于核心線程數(shù),那么即使有空閑線程也不會(huì)復(fù)用線程去執(zhí)行任務(wù),而是創(chuàng)建新的線程去執(zhí)行任務(wù)。如果當(dāng)前執(zhí)行任務(wù)數(shù)量大于核心線程數(shù),此時(shí)再提交任務(wù)就在隊(duì)列中等待,直到有可用線程。
用法:
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread() + ":" + index);
}
});
}
}
定義一個(gè)線程數(shù)為3的線程池,循環(huán)10次執(zhí)行,可以發(fā)現(xiàn)運(yùn)行的線程永遠(yuǎn)只有三個(gè),結(jié)果如下:
Thread[pool-1-thread-1,5,main]:0
Thread[pool-1-thread-2,5,main]:1
Thread[pool-1-thread-3,5,main]:2
Thread[pool-1-thread-1,5,main]:3
Thread[pool-1-thread-2,5,main]:4
Thread[pool-1-thread-3,5,main]:5
Thread[pool-1-thread-1,5,main]:6
Thread[pool-1-thread-2,5,main]:7
Thread[pool-1-thread-3,5,main]:8
Thread[pool-1-thread-1,5,main]:9
newSingleThreadExecutor:單線程線程池
源碼:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
從源碼就可以看出,該線程池基本就是只有一個(gè)線程數(shù)的newFixedThreadPool,它只有一個(gè)線程在工作,所有任務(wù)按照指定順序執(zhí)行。
用法:
和newFixedThreadPool類似,只是一直只有一個(gè)線程在工作,這里就不貼代碼了。
newScheduledThreadPool:支持定時(shí)的定長(zhǎng)線程池
源碼:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
newScheduledThreadPool的方法不是直接返回一個(gè)ThreadPoolExecutor實(shí)例,而是通過(guò)有定時(shí)功能的ThreadPoolExecutor,也就是ScheduledThreadPoolExecutor 來(lái)返回ThreadPoolExecutor實(shí)例,從源碼中可以看出:
1、該線程池可以設(shè)置核心線程數(shù)量,最大線程數(shù)與newCachedThreadPool一樣,都是Integer.MAX_VALUE。
2、該線程池采用的隊(duì)列是DelayedWorkQueue,具有延遲和定時(shí)的作用。
用法:
public static void main(String[] args) {
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
//延遲3秒執(zhí)行,只執(zhí)行一次
((ScheduledExecutorService) scheduledThreadPool).schedule(new Runnable() {
@Override
public void run() {
System.out.println("延遲========");
}
},3,TimeUnit.SECONDS);
//延遲1秒后每隔兩秒執(zhí)行一次
((ScheduledExecutorService) scheduledThreadPool).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("執(zhí)行============");
}
},1,2,TimeUnit.SECONDS); //單位是秒
}
自定義ThreadFactory
四種線程池的使用就說(shuō)到這里了,值得說(shuō)明的是,除了上面的參數(shù)外,Executors類中還給這四種線程池提供了可傳ThreadFactory的重載方法,以下是它們的源碼:
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(),
threadFactory));
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue(),
threadFactory);
}
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(),
threadFactory);
}
ThreadFactory是一個(gè)接口類,也就是我們經(jīng)常說(shuō)的線程工廠,只有一個(gè)方法,可以用于創(chuàng)建線程:
Thread newThread(Runnable r);
默認(rèn)情況下,ThreadPoolExecutor構(gòu)造器傳入的ThreadFactory 參數(shù)是Executors類中的defaultThreadFactory(),相當(dāng)于一個(gè)線程工廠,幫我們創(chuàng)建了線程池中所需的線程。
除此之外,我們也可以自定義ThreadFactory,并根據(jù)自己的需要來(lái)操作線程,下面是實(shí)例代碼:
public static void main(String[] args) {
ExecutorService service = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
new SynchronousQueue(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
System.out.println("我是線程" + r);
return t;
}
}
);
//用lambda表達(dá)式編寫(xiě)方法體中的邏輯
Runnable run = () -> {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "正在執(zhí)行");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
for (int i = 0; i < 5; i++) {
service.submit(run);
}
//這里一定要做關(guān)閉
service.shutdown();
}
運(yùn)行代碼后,控制行會(huì)輸出五行 “我是線程java.util.concurrent.ThreadPoolExecutor。。。。。”的信息,也證明了我們自定義的ThreadFactory起到了作用。
總結(jié)
以上是生活随笔為你收集整理的java 线程工厂_Java并发编程:Java的四种线程池的使用,以及自定义线程工厂的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Svm实现多分类
- 下一篇: java美元兑换,(Java实现) 美元