如何替 ExecutorService 所管理的 thread 設定一個自己看得爽的名子
其實這是一件很重要的事情,根據 clean code 裡面所提到的,一個好的名子可以幫助你理解程式碼並 debug,通常配合 thread 觀測工具就可以找出到底有多少莫名其妙的 thread 在消耗你的資源。
看得這邊你可能會覺得這篇很廢,不過是替 thread 取個名子,原生就有啦
Thread thread = new Thread(Runnable); thread.setName("Load bitmap task");
但是~~~
如果是使用 ExecutorService 做為 thread 排程工具的話,就會發現居然沒有 setName() 可以用,這不是當然的嗎!就算可以取名子也會變成取 ExecutorService 的名子吧。而預設在 thread pool裡的 thread 一律是這格式(如上圖)
String namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-" + thredNumber.getAndIncrement();
基本上這命名有跟沒有差不多,只不過多知道這是由 pool 建出來的,為了解決這個問題,先提供最簡單的土砲法-直接在runnable 把 thread 抓出來命名
new Runnable () { public void run() { Thread.currentThread().setName("Your name"); doStuff(); } }
但是這真的太土砲了,實在沒有美感,也代表者有跑到這個 runnable 的 thread 才有機會被命名,而且如果任務不同的話,一個thread 更有可能會常常變換名稱。
最好的方法是利用工廠模式,在創建 thread pool 時把創造 thread 的工廠方法也放進去
ExecutorService mPool; public ExecutorService getExecutorPool() { if (mPool == null) { mPool = Executors.newFixedThreadPool(POOL_THREAD_NUM, new NameThreadFactory(TAG)); } return mPool; } } // 另外寫的 thread factory, 簡單只多加命名的工作 public class NameThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; public NameThreadFactory(String namePrefix) { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); this.namePrefix = namePrefix + "-" + 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; } }
或者更簡單的使用已有的車輪 guava , google common lib
先必須在 gradle 加上
compile 'com.google.guava:guava:18.0'
接者~
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() .setNameFormat("workerthread-%d").build()
也或者 apache 的這一套 lib ,請先抓jar下來
BasicThreadFactory factory = new BasicThreadFactory.Builder() .namingPattern("workerthread-%d") .daemon(true) .build();
感謝收看
reference:
http://stackoverflow.com/questions/6113746/naming-threads-and-thread-pools-of-executorservice