Java线程工厂问题

4

在我的应用程序中,我使用了一个具有自定义ThreadFactory的线程池。

我的代码如下:

pool = Executors.newScheduledThreadPool(10, new TF());

class TF implements ThreadFactory {
    AtomicInteger count = new AtomicInteger(1);
    public synchronized Thread newThread(Runnable r) {
        Thread t = new Thread(r) ;
        t.setName("ThreadPool Thread[" + count.getAndIncrement() + "]");
        t.setUncaughtExceptionHandler(new UEHLogger());
        return t;
    }
}

然而,当我将各种Runnables提交给线程池后,如果我从IDE(Intellij IDEA)中转储当前线程,我会得到:

"ThreadPool Thread[1]" daemon prio=6 tid=0x0334e000 nid=0x1130 waiting on condition [0x0377f000..0x0377fc94]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x22fa7838> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1925)
    at java.util.concurrent.DelayQueue.take(DelayQueue.java:160)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:583)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:576)
    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:619)

"ThreadPool Thread[1]" daemon prio=6 tid=0x0333e400 nid=0x128 waiting on condition [0x0372f000..0x0372fd14]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x22edb9e0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1963)
    at java.util.concurrent.DelayQueue.take(DelayQueue.java:164)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:583)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:576)
    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:619)

同时,对于线程2-9也有类似的堆栈跟踪。

基本上,我得到的线程号不是1,2,3,4,5,6,7,8,9,10,而是1,1,2,3,4,5,6,7,8,9。

一切似乎都工作得很好,但显然令人不安。


1
这真的令人不安,因为newThread方法是同步的。在这种情况下,你甚至不需要使用AtomicInteger... - Jon Skeet
确实。原始的newThread方法没有同步,我以为那就是问题所在。可惜不是。 - PaulJWilliams
只有第一个ID会重复吗?还是其他的ID也会出现多次? - Ronald Wildenberg
啊,找到问题了。我的应用程序应该(哈哈)只有一个线程池或另一个,取决于配置值。我解释配置值的代码出了点问题,所以实际上我创建了正确的线程池,还有另一个只有一个成员的线程池…… - PaulJWilliams
2个回答

5

您是否无意中创建了两个线程池(或两个ThreadFactories)?

可以尝试通过让每个线程输出其线程工厂的ID以及自己的ID来确认这一点。


1

嗯,使用OpenJDK和以下(高度简化的)测试代码无法重现问题。对于您来说,下面的代码输出是什么?

class TF implements ThreadFactory {

    class UEHLogger implements Thread.UncaughtExceptionHandler
    {
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t + " threw exception: " + e);
    }
    }

    AtomicInteger count = new AtomicInteger(1);
    public synchronized Thread newThread(Runnable r) {
        Thread t = new Thread(r) ;
        t.setName("ThreadPool Thread[" + count.getAndIncrement() + "]");
        t.setUncaughtExceptionHandler(new UEHLogger());
        return t;
    }

    public static void main(String[] a)
    {
    TF myTF = new TF();
    Thread[] threads = new Thread[10];
    for(int i = 0; i < threads.length; i++)
        threads[i] = myTF.newThread(new Runnable(){public void run(){}});
    for(Thread t : threads)
        System.out.println(t);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接