2015-11-11 60 views
0

我正在嘗試使用多個線程的代碼。 下面是我的代碼:使用兩個線程在循環中打印數字

package com.thread.practice; 

public class ThreadPratice1 { 

    public static void main(String[] args) { 
     MyRunnable r = new MyRunnable(); 
     Thread t1 = new Thread(r, "Thread 1"); 
     Thread t2 = new Thread(r, "Thread 2"); 
     t1.start(); 
     t2.start(); 
    } 
} 

package com.thread.practice; 

public class MyRunnable implements Runnable { 
    private static int i = 0; 
    @Override 
    public void run() { 
     for(i = 0; i <10;i++){ 
      System.out.println("Thread: "+ Thread.currentThread().getName() 
        +" value of i: "+i); 
      try { 
       //System.out.println("Thread: "+ i); 
       Thread.sleep(1000); 
       //System.out.println("inside runnable: "+Thread.currentThread().getState()); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

但在輸出它總是打印成0 i的值兩倍的開始。

輸出快到有點像這樣:

Thread: Thread 1 value of i: 0 
Thread: Thread 2 value of i: 0 
Thread: Thread 1 value of i: 2 
Thread: Thread 2 value of i: 2 
Thread: Thread 1 value of i: 3 
Thread: Thread 2 value of i: 4 
Thread: Thread 1 value of i: 5 
Thread: Thread 2 value of i: 6 
Thread: Thread 1 value of i: 7 
Thread: Thread 2 value of i: 8 
Thread: Thread 1 value of i: 9 

可能有人請幫助我理解這個問題?

+1

你開始的每個線程在'for'循環中初始化'i'回到'0' – BeyelerStudios

回答

2

因爲i在執行兩個線程時的值爲0

換句話說,線程1和線程2幾乎在同一時間,所以他們兩個在第一個循環中將i設置爲0。

for(i = 0; i <10;i++) { 

然後,線程之間的值發生變化,因爲您使i爲靜態。所以它會在你的兩個線程之間共享。

+0

好的。但是當第一個線程執行時不應該將值增加到1.因此,當第二個線程得到機會時它不應該打印1嗎? –

+0

不,在第一次輸入時它不會將值增加到1,因爲您再次通過說for(i = 0; i <10; i ++)重新初始化'i' { – Salah

2

您將「i」設置爲靜態,這意味着它在所有線程和對象中都是相同的。拿走靜態修改器,你的代碼將正常工作。

編輯:我誤解你asked-沒有設置什麼,我爲0 for循環,它看起來是這樣的:

for(;i<10;i++) { /*mycode*/} 

這二者之一的可能是你想要什麼,無論如何,你的問題有點模糊

0

i的值只有在循環執行後纔會增加for循環。 for循環的執行需要一定的時間。由於您幾乎一起啓動線程,所以在其他線程完成一個循環後,這兩個線程可能會或可能不會打印i。既然你沒有確保線程安全,結果就像你得到的那樣是不可預知的。

0

首先,你不應該使用原始INT型併發,它不是線程安全的,它可能會導致Race Condition

,並嘗試使用AtomicInteger更換int,它是線程安全的。這個例子可能是:

public class ThreadPratice1 { 

    public static void main(String[] args) { 
     AtomicInteger number = new AtomicInteger(0); 
     MyRunnable r = new MyRunnable(number); 
     Thread t1 = new Thread(r, "Thread 1"); 
     Thread t2 = new Thread(r, "Thread 2"); 
     t1.start(); 
     t2.start(); 
    } 
} 

class MyRunnable implements Runnable { 
    private AtomicInteger number; 

    public MyRunnable(AtomicInteger number) { 
     this.number = number; 
    } 

    @Override 
    public void run() { 
     while (number.get() < 10) { 
      System.out.println("Thread: " + Thread.currentThread().getName() 
        + " value of i: " + number.getAndIncrement()); 
     } 
    } 
}