2011-11-17 37 views
1

我有多個線程打印數據。所有數據都打印出來;然而,他們不是爲了。含義線程2開始打印,而線程1尚未完成,這會導致不一致。我如何保證一致性?含義一旦線程1完成,線程2可以打印。Java - Println不是爲了

+0

你想要兩個線程同時執行或線程1完成其運行後執行線程2嗎? –

+0

線程1完成其運行後執行線程2 –

+5

那麼爲什麼你需要兩個線程呢?線程背後的全部想法是同時運行代碼。 –

回答

0

從你的意見,你正在尋找實現1 1 1 1 2 2 2 2所以你需要做的實際上是等待線程1完成,然後再啓動線程2,是這樣的:

Thread1 thread1 = new Thread1(); 
Thread2 thread2 = new Thread2(); 

thread1.start(); 

thread1.join(); // This waits for Thread1 to finish before starting Thread2 
thread2.start(); 

但是,如果你想有兩個線程開始,但有線程2等待通過其處理部分的方式,在等待線程1完成 - 這可以通過一些技巧來完成 - 一個特別想到的 - 使用Semaphore.

例子:

好吧,首先確定你的線程構造函數接受一個信號量,從而:

// Thread2 would be identical wrt the semaphore 
public Thread1(Semaphore semaphore) throws InterruptedException 
{ 
    this.semaphore = semaphore; // store semaphore locally 
    semaphore.acquire(2); 
} 

線程1的run方法應該是這樣的:

public void run() 
{ 
    // .... processing... 

    // ... print stuff 
    System.out.println("1 1 1 1"); 
    semaphore.release(); // release 1 permit, allowing thread2 to continue 

    // ... more processing 

    semaphore.release(); // release last permit. 
} 

線程2的run方法看起來應該類似於此:

public void run() 
{ 
    int permits = 2; 
    try 
    { 
    // .... processing... 

    semaphore.acquire(1); // acquire one more permit (will block until Thread1 releases one) 
    permits++; 

    // ... print stuff 
    System.out.println("2 2 2 2"); 

    // ... more processing  
    } 
    catch (InterruptedException ie) 
    { 
    // interrupted 
    } 

    semaphore.release(permits); // release permits. 
} 

現在,設置線程可以這樣完成:

try 
{ 
    Semaphore semaphore = new Semaphore(4); // 4 permit semaphore 

    Thread1 thread1 = new Thread1(semaphore); 
    Thread2 thread2 = new Thread2(semaphore); 

    thread1.start(); 
    thread2.start(); 

    semaphore.acquire(4); 
} 
catch (InterruptedException ie) 
{ 
    // interrupt logic... 
} 
+0

你能舉個例子嗎?謝謝。 –

+0

如果你只是一次只運行一個線程,爲什麼還要有線程呢? –

+0

信號量方法將允許兩個線程同時執行處理,但允許一個線程中途暫停,允許其他線程繼續處理,然後再恢復自己...現在正在編寫示例... – Crollster

0

這是線程是如何工作的。如果你啓動兩個線程它就會像這樣1 2 1 2 1 2 1 2

+0

是的,這是事實。我想實現1 1 1 1 2 2 2 2 –

+0

不,它不會。訂單沒有保證。 –

0

一旦run方法在一個線程已經完成調用它的東西在線程2讓它知道它可以打印

0

我們無法計算線程何時運行並完成執行。它完全取決於CPU。你可以做的是在第一個線程結束時將一個標誌變量更新爲一個值,並在第二個線程執行之前檢查該值。

0

你必須保存線程2輸出並打印它,直到線程1爲止。按照建議的順序執行它們也會起作用,但那麼爲什麼要使用Thread?

1

如果您希望線程1執行的代碼在運行線程2之前完成,那麼您不需要線程。您可能想看看Java的ExecutorService。具體而言,Executors. newSingleThreadExecutor()。這將允許您安排任務在另一個線程中運行,但要確保它們按順序運行。

1

所以,這裏是你想要做的(僞代碼)是什麼:

String results[2]; 

Thread1 thread1 = new Thread1() { 
    public void run() { 
     // do stuff; collect output 
     results[0] = output 
    } 
}; 

Thread2 thread1 = new Thread1() { 
    public void run() { 
     // do stuff; collect output 
     results[1] = output 
    } 
}; 

thread1.start(); 
thread2.start(); 

thread1.join(); 
thread2.join(); 

print result[0]; 
print result[1]; 

上面有利用java.util.concurrent類做的更好的方法,但是這應該給你一個想法

+0

只有數據輸出被串行化,而不是主要處理。所以你可能仍然會贏得勝利(當然,這取決於運行方法內部發生了什麼)。 –

+0

對不起 - 評論不好的帖子! –

-1

您不能隨機從多個線程打印,並預計任何命令。

如果你需要按照有序的方式輸出,那麼你將不得不同步這些線程(從而破壞具有多個線程的目的),或者讓線程回傳信息以便輸出回主線程它可以處理訂購和輸出它。

編輯:因爲我很無聊。

如果你想通過線程並行化一些工作然後輸出結果,你需要讓線程將他們工作的產品傳回給主線程並讓它做輸出。一種方法,這是使用隊列(這是簡單的例子,它依賴線程順序 - 你可能需要把所有的結果和關聯/排序/等):

public class Worker implements Runnable 
{ 

    private ConcurrentLinkedQueue<Integer> outputQueue; 

    public Worker(ConcurrentLinkedQueue<Integer> outputQueue) 
    { 
     this.outputQueue = outputQueue; 
    } 

    @Override 
    public void run() 
    { 

     // Do whatever it is you're doing 
     ... 
     // place result on queue 
     outputQueue.add(result); 

    } 

} 

public class Main 
{ 

    static void main(String[] args) 
    { 

     ArrayList<ConcurrentLinkedQueue<Integer>> myQueues = 
      new ArrayList<ConcurrentLinkedQueue<Integer>>(); 

     Thread[] myThreads = new Thread[numThreads]; 

     // Create queue, create thread with Worker(queue), 
     // start thread 
     for (int i = 0; i < numThreads; i++) 
     { 
      ConcurrentLinkedQueue<Integer> queue = 
       new ConcurrentLinkedQueue<Integer>(); 

      myQueues.add(queue);   

      myThreads[i] = new Thread(new Worker(queue)).start(); 

     } 

     // Wait for all threads to finish, print their results 
     for (int i = 0; i < numThreads; i++) 
     { 
      join(myThreads[i]); 

      // Get the queue for the thread we just joined, 
      // pull off each result and output 
      Integer j; 
      while ((j = myQueues.get(i).poll()) != null) 
      { 
       System.out.println(j); 
      } 

     } 
    } 
} 

這關的。上面有我頭,但這是一般的方法