Обдумывание ThreadLocal (Или: javadoc Солнца неправильно?)

Я читал о ThreadLocal, пытаясь понять, как он работает и почему нам нужен он.

До сих пор то, что я смог изучить, следующее:

  1. Класс ThreadLocal позволяет содержать 1 экземпляр объекта на уровне потока
  2. Экземпляр создается путем переопределения initialValue ()
  3. Экземпляр на самом деле хранится в HashMap каждого потока
  4. Разумный пример использования может быть найден здесь

Весь казался прекрасным, пока я не пытался выполнить пример от javadoc, код предоставлен как следующее:

 import java.util.concurrent.atomic.AtomicInteger;

 public class UniqueThreadIdGenerator {

     private static final AtomicInteger uniqueId = new AtomicInteger(0);

     private static final ThreadLocal < Integer > uniqueNum = 
         new ThreadLocal < Integer > () {
             @Override protected Integer initialValue() {
                 return uniqueId.getAndIncrement();
         }
     };

     public static int getCurrentThreadId() {
         return uniqueId.get();
     }
 } // UniqueThreadIdGenerator

Если я понимаю, что этот код правильно, звоня getCurrentThreadId () должен возвратить корректное автоматическое увеличенное число потока, увы это возвращается 0 для меня. ВСЕГДА 0, без рассмотрения того, сколько потоков я запустил.

Для получения этой работы для меня, я должен был изменить getCurrentThreadId () для чтения

     public static int getCurrentThreadId() {
         return uniqueId.get();
     } 

В этом случае я получаю правильные значения.

Мой код предоставлен ниже, что я пропускаю? (Не то, чтобы javadoc является на самом деле неправильным, правильно??)

package org.vekslers;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class UniqueThreadIdGenerator extends Thread {

    private static final AtomicInteger uniqueId = new AtomicInteger(0);

    private static final ThreadLocal  uniqueNum = 
        new ThreadLocal  () {
            @Override protected Integer initialValue() {
                return uniqueId.getAndIncrement();
        }
    };

    public static int getCurrentThreadId() {
        return uniqueNum.get();
    }




    //////////////////////////////////////////////////
    // Testing code...
    //////////////////////////////////////////////////
    private static volatile boolean halt = false;

    public UniqueThreadIdGenerator(String threadName) {
        super(threadName);
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread() + " PREHALT " + getCurrentThreadId());
        while(!halt)
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
            }
        System.out.println(Thread.currentThread() + " POSTHALT " + getCurrentThreadId());
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new UniqueThreadIdGenerator("t1");
        Thread t2 = new UniqueThreadIdGenerator("t2");
        Thread t3 = new UniqueThreadIdGenerator("t3");
        Thread t4 = new UniqueThreadIdGenerator("t4");

        t3.start();
        t1.start();
        t2.start();
        t4.start();

        TimeUnit.SECONDS.sleep(10);
        halt = true;
    }
} // UniqueThreadIdGenerator

Вывод:

Thread[t3,5,main] PREHALT 0
Thread[t1,5,main] PREHALT 1
Thread[t2,5,main] PREHALT 2
Thread[t4,5,main] PREHALT 3
Thread[t4,5,main] POSTHALT 3
Thread[t2,5,main] POSTHALT 2
Thread[t1,5,main] POSTHALT 1
Thread[t3,5,main] POSTHALT 0

p.s. Комментарии к коду OT или к точке приветствуются в комментариях.

5
задан Community 23 May 2017 в 12:25
поделиться

1 ответ

Документы javadoc неверны.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6475885

javadoc Java 7 включает

 import java.util.concurrent.atomic.AtomicInteger;

 public class ThreadId {
     // Atomic integer containing the next thread ID to be assigned
     private static final AtomicInteger nextId = new AtomicInteger(0);

     // Thread local variable containing each thread's ID
     private static final ThreadLocal<Integer> threadId =
         new ThreadLocal<Integer>() {
             @Override protected Integer initialValue() {
                 return nextId.getAndIncrement();
         }
     };

     // Returns the current thread's unique ID, assigning it if necessary
     public static int get() {
         return threadId.get();
     }
 }
9
ответ дан 14 December 2019 в 01:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: