2015-07-05 22 views
7

Aynı anda birçok iş parçacığından erişilmesi gereken bir alan var. x'un her bir iş parçacığı için ayrı bir kopyasına sahip olmasını istiyorum, her biri özgün değerinden başlıyor. Bunu volatile anahtar sözcüğünü kullanarak yapmaya çalıştım, ancak her yeni iş parçacığı, diğer iş parçacıkları için hala x değiştirir. Her iş parçacığı için ayrı x değerini tutmak nasılHer bir iş parçacığı için ayrı ayrı durum nasıl sağlanır

x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 
x=1 | thread id=10| 100*x+x=101 //thread 10 has x field value as 1 
x=2 | thread id=11| 100*x+x=202 //thread 11 modifies x field to 2 
x=2 | thread id=10| 100*x+x=202 //thread 10 lost x value as 1 :(

etc... 

veya çözmek için daha optimum bir yolu vardır:

public class StackOverflowThread0 { 

    public StackOverflowThread0() { 
     new A().start(); 
    } 

    public static void main(String[] args) { 
     new StackOverflowThread0(); 
    } 

    volatile int x = 0;//<--keep original for each thread? 

    class A extends Thread { 

     @Override 
     public void run() { 
      try { 
       while (true) { 
        getT().start(); 

        Thread.sleep(1000); 
       } 
      } catch (InterruptedException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 

    Thread getT() { 
     Thread t = new Thread() { 

      @Override 
      public void run() { 
       x++; 

       for (int i = 0; i < 100; i++) { 
        try { 
         System.out.println("x=" + x + " | thread id=" + Thread.currentThread().getId() + "| 100*x+x=" + (100 * x + x)); 
         Thread.sleep(100); 
        } catch (InterruptedException ex) { 
         ex.printStackTrace(); 
        } 
       } 
       interrupt(); 
      } 
     }; 
     return t; 
    } 
} 

çıktı: İşte

bir kod örneği görev?

+4

Bir göz atın: http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html –

+0

@TotZam evet, atomik denedim ama işe yaramadı gibi görünüyor açıkladığım durum; Her neyse biraz daha sonra tekrar deneyeceğim :) – user390525

+0

@TotZam Her iş parçacığı için ortak bir değer değil, her iş parçacığı için ayrı bir değer olduğunu düşünüyorum. –

cevap

4

Bu, sizin için ThreadLocal sınıfı yapabilir. Erişen her bir iş parçacığı için farklı olan bir değişkeni korur. Diğer bir deyişle, her bir iş parçacığı değişkenin kendine özgü bir kopyasını alır. Kodunuza aşağıdaki değişiklikler dışında

Kontrol:

//Initialisation of the variable. Here an initial value of zero is assigned. 
ThreadLocal<Integer> x = ThreadLocal.withInitial(()-> 0); 

//Incrementing the value by one: 
x.set(x.get() + 1); 

//Outputting the result: 
System.out.println("x=" + x.get() + " | thread id=" 
          + Thread.currentThread().getId() + "| 100*x+x=" + (100 * x.get() + x.get())); 

Düzenleme: 1.7 kullananlar için gerçekten lambda ifadesi olmadan ThreadLocal kullanmak için bir yolu yoktur. Yine de, initialValue() yöntemini geçersiz kılmanız gerekir.

ThreadLocal<Integer> x = new ThreadLocal<Integer>() { 
    @Override 
    protected Integer initialValue() { 
     return 0; 
    } 
}; 
+0

Lambda ifadelerinden kaçınarak aynı sonucu elde etmenin bir yolu var mı? Şu anda 1.7 kullanıyorum – user390525

+0

ThreadLocal mı iplik 10 ve iplik 11, örneğin kendi x değerinin 1 olduğu anlamına gelir, böylece x değeri çoğaltılabilir veya eklenemez? Daha fazla ayrıntı ver – user390525

+0

Her yeni bir thread, threadLocal.get aracılığıyla değişkene erişmeye çalıştığında(), yeni bir Tamsayı örneği, initialValue() yöntemi kullanılarak otomatik olarak oluşturulur. Bu Tamsayı örneği bir iş parçacığına aittir ve diğer tüm iş parçacıklarına görünmez. Umarım bunu açıklar. –

3

Alternatif size çağrı yığını üzerinde x değişken tutabilir, yerel depolama Konu için. Elbette bu, x'u nasıl kullandığınıza bağlıdır; Değişkeninize gerçekten yığında ihtiyacınız olabilir. Ve bu durumda ThreadLocal ile daha iyi durumdasın.

Hepsini aç Hepsini kapa Belirtiler Bir yığın paylaşır, ancak have their own stack.

Bu, yığınta tutulan değişkenlerin hemen yerel olarak işlendiği anlamına gelir.

+0

Kutunun dışında düşünmek için güzel bir, +1. –

+0

Ben de böyle düşündüm ama oldukça irrasyonel :) Bir geçici çözüm olarak her overriden run() yönteminde int mX = x'i entegre etmeye çalıştım; Ama, evet, ThreadLocal "x yinelenecek tamam" sorunu çözmek için standart bir yol gibi görünüyor – user390525

İlgili konular