“ 使用ThreadFactory可以控制线程池内,线程创建前的行为”
01
—
说明
全路径java.util.concurrent.ThreadFactory
是一个接口,内部只声明了一个newThread方法
接口声明如下
public interface ThreadFactory {Thread newThread(Runnable r);}
02
—
原理
我们通常使用线程池的submit方法将任务提交到线程池内执行。
如果此时线程池内有空闲的线程,则会立即执行该任务,如果没有则需要根据线程池的类型选择等待,或者新建线程。
所以线程池内的线程并不是线程池对象初始化(new)的时候就创建好的。而是当有任务被提交进来之后才创建的,而创建线程的过程是无法干预的。
如果我们想在每个线程创建时记录一些日志,或者推送一些消息那怎么做?
就可以使用ThreadFactory来达到目的,让线程池内的每个线程都通过ThreadFactory来创建。
02
—
使用案例
使用ThreadFactory十分简单
第一步: 编写ThreadFactory接口的实现类
第二步: 创建线程池时传入ThreadFactory对象
案例:希望在线程创建的时候输出日志,并且给每个线程起一个自己的名字
(提醒:代码可复制粘贴直接运行)
第一步:编写ThreadFactory接口的实现类
(代码较大请横向滑动或使用PC查看)
import java.util.concurrent.ThreadFactory;import java.util.concurrent.ThreadLocalRandom;/*** 线程工场*/class DemoThreadFactory implements ThreadFactory {是否记录日志,true输出日志,false不输出日志private boolean saveLog;工场名称private String factoryName;public DemoThreadFactory(String factoryName, boolean saveLog) {this.factoryName = factoryName;this.saveLog = saveLog;}public Thread newThread(Runnable r) {if (saveLog) {动态输出日志System.out.println(System.currentTimeMillis() + this.factoryName + " create start");}Thread thread = new Thread(r);自定义线程名字thread.setName("Kevin-Thread-" + thread.getName() + ":" + thread.getId());try {模拟初始化时间Thread.sleep(ThreadLocalRandom.current().nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}if (saveLog) {System.out.println(System.currentTimeMillis() + this.factoryName + " " + thread.getName() + " create end");}return thread;}}
第二步:创建线程池时传入ThreadFactory对象
(代码较大请横向滑动或使用PC查看)
/*** 使用线程工场创建线程*/public class ThreadFactoryDemo0 {public static void main(String[] args) {//创建任务对象Runnable runnable = new Runnable() {public void run() {System.out.println(Thread.currentThread().getName() + " run");}};System.out.println("newCachedThreadPool使用ThreadFactory");//创建自定义线程工场DemoThreadFactory threadFactory = new DemoThreadFactory("newCachedThreadPoolFactory",true);//使用线程工场初始化线程池ExecutorService executorService = Executors.newCachedThreadPool(threadFactory);for (int i = 0; i < 3; i++) {executorService.execute(runnable);}executorService.shutdown();System.out.println("newFixedThreadPool使用ThreadFactory");//创建自定义线程工场threadFactory = new DemoThreadFactory("newFixedThreadPoolFactory",true);//使用线程工场初始化线程池executorService = Executors.newFixedThreadPool(2, threadFactory);for(int i=0;i<3;i++){executorService.execute(runnable);}executorService.shutdown();//创建其他线程池也可以使用ThreadFactory//Executors.newScheduledThreadPool(2,threadFactory);//Executors.newSingleThreadExecutor(threadFactory);//Executors.newSingleThreadScheduledExecutor(threadFactory);}}
运行结果
---------------------------------------------newCachedThreadPool使用ThreadFactory---------------------------------------------1573661399611newCachedThreadPoolFactory create start1573661400155newCachedThreadPoolFactory Kevin-Thread-Thread-0:11 create end1573661400155newCachedThreadPoolFactory create startKevin-Thread-Thread-0:11 run1573661400755newCachedThreadPoolFactory Kevin-Thread-Thread-1:12 create end---------------------------------------------newFixedThreadPool使用ThreadFactory---------------------------------------------1573661400756newFixedThreadPoolFactory create startKevin-Thread-Thread-0:11 runKevin-Thread-Thread-1:12 run1573661401042newFixedThreadPoolFactory Kevin-Thread-Thread-2:13 create end1573661401043newFixedThreadPoolFactory create startKevin-Thread-Thread-2:13 run1573661401445newFixedThreadPoolFactory Kevin-Thread-Thread-3:14 create endKevin-Thread-Thread-3:14 runKevin-Thread-Thread-2:13 run
想快速精通并发编程,点击公众下方的“阅读原文” 学习由Kevin本人录制的《JAVA并发编程-豪华版》课程。

▼阅读原文了解我课程 。和朋友一起在看▼
文章转载自尹洪亮Kevin,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




