2010-06-21 3 views
5

Ho letto su ThreadLocal, cercando di capire come funziona e perché ne abbiamo bisogno.ThreadLocal pondering (Oppure: javadoc del sole è sbagliato?)

Finora quello che ho potuto imparare è la seguente:

  1. classe ThreadLocal permette di tenere 1 istanza di un oggetto a livello di thread
  2. L'istanza viene creato sovrascrivendo initialValue()
  3. l'istanza viene effettivamente memorizzato nell'esempio utilizzo each thread's HashMap
  4. Un buon senso can be found here
.515.053.691,36321 milioni

Tutto sembrava bene, fino a quando ho provato a eseguire l'esempio dal javadoc, il codice viene fornito come segue:

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 

Se ho capito questo codice correttamente, chiamando GetCurrentThreadId() dovrebbe restituire l'auto incrementato numero di thread corretto , purtroppo restituisce 0 per me. SEMPRE 0, senza considerare il numero di thread che ho avviato.

per ottenere questo lavoro per me ho dovuto cambiare GetCurrentThreadId() per leggere

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

In questo caso sto ottenendo valori corretti.

Il mio codice è fornito di seguito, cosa mi manca? (Non è che il javadoc in realtà è sbagliato, giusto ??)

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 

uscita:

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. Codice commenti OT o al punto sono i benvenuti nei commenti.

risposta

9

Le javadoc sono sbagliate.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6475885

Java 7's javadoc include

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

Incredibile, questo bug è quasi 4 anni. Ci vogliono 4 anni per correggere un refuso del manuale html su un server web. Nel frattempo c'erano 20 versioni di aggiornamento. Incredibile .... –

+2

@Peter Le specifiche non possono essere modificate in una versione di aggiornamento. Puoi vedere che il bug è stato effettivamente corretto anni fa. –

+0

Grazie per l'avviso. –