写了一个多线程socket送信并获得线程ID的demo,运行结果不对,不知道是哪的问题public class threadTest {   
       
 //private final static InheritableThreadLocal<String> holder = new InheritableThreadLocal<String>();   
 public static void main(String[] args){   
     
     thread tt = new thread();
     Thread t = new Thread(tt);
     t.start();
 }
}
public class thread implements Runnable {    public thread() {
        // TODO Auto-generated constructor stub
    }    @Override
    public void run() {
        ExecutorService executor = null;
        executor = Executors.newCachedThreadPool();
        
        try {
            ServerSocket socket = new ServerSocket(80);
        
        System.out.println("ServerSocket接続");
        while (true) {
            final Socket connection = socket.accept();            TransactionId.newId();
            System.out.println("TransactionIdbegin=" + TransactionId.get());
            executor.execute(new Runnable() {                public void run()
                {
                    System.out.println("TransactionIdend=" + TransactionId.get());
                }
            });  
        }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    }}
public final class TransactionId {      private static final AtomicLong currentId = new AtomicLong();
      private static final InheritableThreadLocal<String> transactionId = new InheritableThreadLocal<>();     private TransactionId() {
    }
    
    public synchronized static void newId() {
        transactionId.set(String.format("%010d", currentId.incrementAndGet()));
        
        //currentId ++;
        //transactionId.set(String.format("%010d", currentId));
    }       public static String get() {
        return transactionId.get();
    }}结果:
TransactionIdbegin=0000000001
TransactionIdend=0000000001
TransactionIdbegin=0000000002
TransactionIdend=0000000001 (为什么不是2呢)
多线程socketjava

解决方案 »

  1.   

    ThreadLocal有个缺陷,在子线程里无法访问父线程的变量, 
    InheritableThreadLocal 解决了这个问题,自动会把父线程的变量传递个子线程, 
    子线程只能用,修改了不会影响父线程的东西 
      

  2.   

    ThreadLocal是以ThreadID作为key的你把线程的id打出来看看。 
      

  3.   

    结果:
    TransactionIdbegin=0000000001
    TransactionIdend=0000000001
    TransactionIdbegin=0000000002
    TransactionIdend=0000000001 (为什么不是2呢)大概过一段时间(60s)就对了
    TransactionIdbegin=0000000003
    TransactionIdend=0000000003感觉是线程乱了,但是不知道问题在哪,希望大侠能帮忙分析一下。
      

  4.   

    两次调用的get方法,他们的caller不是同一个线程。
    由于使用了ThreadLocal变量,所以,每个线程会单独保存一份各自的值。
    不同线程,保存的值自然可能不会相同。
      

  5.   

    初始化的时候是在主线程中,get的时候是在子线程中,ThreadLocal只能保证当前线程的线程安全吧。要是把初始化放到子线程中,应该就没有问题了
      

  6.   

    我用的不是ThreadLocal,而是InheritableThreadLocal 。》ThreadLocal有个缺陷,在子线程里无法访问父线程的变量, 
    》InheritableThreadLocal 解决了这个问题,自动会把父线程的变量传递个子线程, 
    》子线程只能用,修改了不会影响父线程的东西  
      

  7.   

    InheritableThreadLocal 变量值会自动传递给所有子线程。
      

  8.   

    提出解决方案,
    public class thread implements Runnable {    public thread() {
            // TODO Auto-generated constructor stub
        }    @Override
        public void run() {
            ExecutorService executor = null;
            executor = Executors.newCachedThreadPool();
            
            try {
                ServerSocket socket = new ServerSocket(80);
            
            System.out.println("ServerSocket接続");
            while (true) {
                final Socket connection = socket.accept();            TransactionId.newId();
                final String transactionId = TransactionId.get();
                System.out.println("TransactionIdbegin=" + transactionId);
                
                executor.execute(new Runnable() {
                    public void run()
                    {
                        System.out.println("TransactionIdend=" + transactionId);
                    }
                });  
            }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }    }}