2010-06-21 40 views
5

J'ai lu ThreadLocal, essayant de comprendre comment cela fonctionne et pourquoi nous en avons besoin.ThreadLocal songering (Ou: Le javadoc du soleil est-il faux?)

Jusqu'à présent, ce que je suis en mesure d'apprendre est le suivant:

  1. classe ThreadLocal permet de tenir une instance d'un objet au niveau du fil
  2. L'instance est créée en remplaçant initialValue()
  3. l'instance est stocké dans le each thread's HashMap
  4. Un usage bon sens exemple can be found here

Tout semblait bien, jusqu'à ce que j'ai essayé de courir l'exemple de la javadoc, le code est fourni ci-dessous:

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 

Si je comprends ce code correctement, appelant GetCurrentThreadId() renvoie le nombre de threads incrémentée de correction automatique , hélas ça revient 0 pour moi. TOUJOURS 0, sans tenir compte du nombre de threads que j'ai démarré.

Pour obtenir ce travail pour moi que je devais changer GetCurrentThreadId() pour lire

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

Dans ce cas, je recevais des valeurs correctes.

Mon code est fourni ci-dessous, que manque-t-il? (Ce n'est pas que le javadoc est en fait mal, droit ??)

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 

Sortie:

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. Les commentaires de code OT ou au point sont les bienvenus dans les commentaires.

Répondre

9

Les javadocs sont incorrects.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6475885

Java 7's javadoc comprend

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

Incroyable, ce bug est près de 4 ans. Il faut 4 ans pour corriger une faute de frappe du manuel html sur un serveur web. Entre-temps, il y a eu 20 mises à jour. Incroyable .... –

+2

@Peter La spécification ne peut pas être modifiée dans une version de mise à jour. Vous pouvez voir que le bug a été corrigé il y a des années. –

+0

Merci pour l'avis. –