2010-06-21 57 views
5

我一直在阅读有关ThreadLocal,试图了解它是如何工作的,以及为什么我们需要它。ThreadLocal沉思(或:太阳的javadoc错了?)

到目前为止,我已经能够学到如下:

  1. 的ThreadLocal类允许线程级持有对象的1个实例
  2. 实例是通过覆盖初值创建()
  3. 实例实际上是存储在each thread's HashMap
  4. 甲常识使用例can be found here

一切似乎都很好,直到我试图运行从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 <Integer> uniqueNum = 
     new ThreadLocal <Integer>() { 
      @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 

附:代码评论OT或点在欢迎的意见。

回答

9

javadocs是错误的。
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6475885

Java 7's javadoc包括

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(); 
    } 
} 
+0

最好的,这个错误几乎是4岁。需要4年才能在Web服务器上修复HTML手册的错误。与此同时,有20个更新版本。令人惊叹...... – 2010-06-22 00:27:03

+2

@Peter在更新版本中无法更改规范。您可以看到该错误实际上是在几年前修复的。 – 2010-06-22 00:42:10

+0

感谢您的通知。 – 2010-06-22 06:01:06