为何需要定制化的Thread Factory?
来源:互联网 发布:知乎 和父母吵架 编辑:程序博客网 时间:2024/05/17 01:40
当我们提交任务到Executor框架中时,一个线程会负责执行该任务。该线程有可能从线程池中分配,也有可能是按需创建。每一个Executor都对应一个ThreadFactory。如果我们在创建Executor的时候没有明确知道指定ThreadFactory,那么Executor会使用缺省的ThreadFactory.
我们来看一下JDK1.6中java.util.concurrent.Executors使用的DefaultThreadFactory.
/** * The default thread factory */ static class DefaultThreadFactory implements ThreadFactory { static final AtomicInteger poolNumber = new AtomicInteger(1); final ThreadGroup group; final AtomicInteger threadNumber = new AtomicInteger(1); final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null)? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }
既然Java concurrent包已经提供了缺省的Thread Factory,那么我们为何还要使用定制化的工厂呢?原因如下:
为了能够设置一个更有意义的线程名.
在DefaultThreadFactory中创建的线程名字格式为pool-m-thread-n, 也就是pool-1-thread-2,pool-2-thread-3,完全看不出该线程为何创建,在做什么事情。在调试、监控和查看日志时非常不便。尤其是在分析thread dump时,线程名是确认线程由哪个Executor或thread pool创建和了解线程信息的重要线索。 在stack trace中,往往从头到尾都是JDK的类,很难知道这个线程是做什么的。一个有意义的线程名可以帮助我们迅速地定位问题。
"pool-7-thread-8011" id=29794 TIMED_WAITING waiting on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@3a11cf61 at sun.misc.Unsafe.park (Unsafe.java) (native) at java.util.concurrent.locks.LockSupport.parkNanos (LockSupport.java:196) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos (AbstractQueuedSynchronizer.java:2025) at java.util.concurrent.DelayQueue.take (DelayQueue.java:164) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take (ScheduledThreadPoolExecutor.java:609) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take (ScheduledThreadPoolExecutor.java:602) at java.util.concurrent.ThreadPoolExecutor.getTask (ThreadPoolExecutor.java:947) at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:907) at java.lang.Thread.run (Thread.java:662)
自主选择线程类型:守护线程或用户线程
DefaultThreadFactory创建的线程类型均为用户线程,不能创建守护线程。
只要有用户线程尚在,JVM就不会退出。而一旦最后一个用户线程结束,即使还有守护线程运行,那么JVM也会退出。对于一些后台服务,我们更倾向于使用守护线程,比如Garbage Collector就是一个守护线程。
线程优先级
DefaultThreadFactory创建的线程优先级均为NORM_PRIORITY,高优先级的线程更容易得到调度,因此使用自定义的Thread Factory可以指定所创建线程的优先级。处理未捕捉的异常
在执行一个任务时,线程可能会由于未捕获的异常而终止,默认处理是将异常打印到控制台。但这种处理方式有时并非你所想要的,存放如文件或者db会更合适。所以可以在自定义的Thread Factory中指定UncaughtExceptionHandler,发生异常时便会按照预期的逻辑执行。
下面是我为了能够指定更有意义的线程名所写的一个Thread Factory.
static class SelfDefinedThreadFactory implements ThreadFactory { final AtomicInteger threadNumber = new AtomicInteger(1); final String namePrefix; SelfDefinedThreadFactory(String namePrefix) { this.namePrefix = namePrefix+"-"; } public Thread newThread(Runnable r) { Thread t = new Thread( r,namePrefix + threadNumber.getAndIncrement()); if (t.isDaemon()) t.setDaemon(true); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }private ExecutorService executor = Executors.newFixedThreadPool(50, new SelfDefinedThreadFactory("MessageProcessor"));
- 为何需要定制化的Thread Factory?
- 为何网站需要静态化
- 为何退出thread或者创建thread失败时,需要调用pthread_attr_destroy?
- 为何退出thread或者创建thread失败时,需要调用pthread_attr_destroy?
- Yii2 restful api 定制化返回 自己需要的结构
- 手机游戏为何需要强烈的“心跳”?
- 为何定制的系统,长按触摸屏没有右键菜单?
- 程序都是通用的,我们需要定制
- Android Activity定制需要的Title
- Android Activity定制需要的Title
- 为什么我们需要软件定制化?
- lua multiple thread 需要注意的事情
- 为何需要 SOA ?
- 为何需要重构
- 为何我们需要鼠标?
- 为何需要核函数
- 你为何需要iPhone6?
- 为何需要代码审查
- 为什么你越努力,却越焦虑?
- Fragment侧滑翻页
- 通过Windows注册表获取U盘、移动硬盘和USB读卡器等设备的PID、VID和序列号
- 华为机试——查找字符串中空格分割的单词的最大长度
- 【LEETCODE】142-Linked List Cycle II
- 为何需要定制化的Thread Factory?
- I,P,B帧和PTS,DTS的关系
- iOS setter 与 getter方法
- STM32 printf函数的调用
- g++编译出的多线程程序出错“segmentation fault"
- mysql错误:my_config.h: No such file or directory
- 信息学奥林匹克竞赛-三连击
- Xcode如何在自己的工程中引入另外一个工程及相关错误的解决办法
- 负载均衡和集群