Проблема с Java ThreadFactory - PullRequest
4 голосов
/ 28 апреля 2009

В моем приложении я использую пул потоков с пользовательской фабрикой потоков.

Мой код выглядит так:

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

Кажется, все работает хорошо, но это явно сбивает с толку.

Ответы [ 2 ]

5 голосов
/ 28 апреля 2009

Вы случайно не создали два пула потоков (или два ThreadFactories), не так ли?

Может быть, идея подтвердить это, заставив каждый поток выводить идентификатор своей фабрики потоков вместе со своим собственным идентификатором.

1 голос
/ 28 апреля 2009

Хм, не могу воспроизвести проблему с 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);
    }
}
...