簡體   English   中英

Java中的線程同步

[英]Threads synchronization in Java

我有一個類似的場景。...有四個線程分別命名為Thread1,Thread2,Thread3和Thread4。 並且有一個計數器變量。 我想輸出如下

Thread1 : value of counter variable is = 0
Thread2 : value of counter variable is = 1
Thread3 : value of counter variable is = 2
Thread4 : value of counter variable is = 3

Thread1 : value of counter variable is = 4
Thread2 : value of counter variable is = 5
Thread3 : value of counter variable is = 6
Thread4 : value of counter variable is = 7

Thread1 : value of counter variable is = 8
Thread2 : value of counter variable is = 9
Thread3 : value of counter variable is = 10
Thread4 : value of counter variable is = 11

甚至我在邏輯上也做到了。 但是我想要類似的東西,當Thread1正在打印counter變量時,所有其余線程都應等待.....然后在Thread2之后出現圖片並打印counter變量,其余應等待。

建議我為此的最佳解決方案。 提前致謝 :-)

除了了解同步,這幾乎沒有意義。 我會使用CyclicBarrier來做到這一點。 這是一個相當高級的抽象,因此您不必自己使用wait()notifiy()

或者,您可以使用IntegerAtomicInteger對象作為變量,並將其傳遞到線程周圍(每個對象都應提供可被另一個線程調用的consume(Integer i)方法,然后遞增並打印該值並將其傳遞給下一個螺紋)。 在此變體中,同步在代碼中隱式處理。

我不確定你想要什么。 您是否要讓線程按順序增加並打印變量? 這沒有任何意義,線程是獨立的,並且可以同時運行。 那就是他們的目的。

因此,讓我直接講:您想使用並行處理來進行串行工作。

基本上,您要做的是:

for(int i=0;i<10;i++)
    System.out.println(i);

但是然后有線程。

線程用於並行處理事務。 那就是他們的目的。 試圖將串行問題強加給這個概念,不僅會減慢您的應用程序的速度,而且會使它更容易出錯。

當然,除非您的這個示例非常簡化。 也許您需要提供更多信息以幫助我們,然后...

這是一個有趣的問題,因為線程被設計為獨立地並排工作,而不是嚴格地鎖定在一起。

我認為最簡單的方法是使用公平的ReentrantLockAtomicInteger和一些謹慎的設置(以確保線程以正確的順序開始在ReentrantLock上等待)。

您的主線程將需要初始化計數器,創建鎖對象並對其進行鎖定,然后依次啟動四個子線程,確保在關閉下一個線程之前,每個子線程都到達了鎖。

當所有4個線程准備就緒時,您可以釋放鎖並讓其他線程運行。

每個工作線程應從計數器中獲取值,將其遞增,顯示計數器,然后釋放鎖(這將使下一個線程運行),然后再重新獲取它。

請注意,這里仍然存在競爭條件:線程2可能在線程1開始再次等待鎖之前繞循環運行,因此這兩個線程最終將以相反的順序運行。 要解決此問題,輔助線程需要等待,直到有足夠多其他線程在等待,直到它們在循環中繼續進行為止(當然,最后一次迭代除外)。 不太好,但是由於列出的限制,我擔心這很重要。

這不是簡單的代碼。 我認為,這里要學習的教訓是,您不應該真正使用多個線程來執行固有的串行工作! 要么,要么您不必在乎哪個線程執行哪個串行操作。

我找到了解決此問題的兩種方法。...但仍在等待專家評論...。

第一種方式:-----

包semafore;

導入java.util.concurrent.Semaphore;

公共類Main {公共靜態void main(String args [])引發異常{Semaphore sem = new Semaphore(1,true); 線程thrdA = new Thread(new SyncOutput(sem,“ Thread1”)); 線程thrdB = new Thread(new SyncOutput(sem,“ Thread2”)); 線程thrdC =新線程(新SyncOutput(sem,“ Thread3”)); 線程thrdD =新線程(新SyncOutput(sem,“ Thread4”));

    thrdA.start();
    thrdB.start();
    thrdC.start();
    thrdD.start();

    thrdA.join();
    thrdB.join();
    thrdC.join();
    thrdD.join();

}

}

SyncOutput類實現Runnable {Semaphore sem; 字符串味精; 私有靜態int val = 0;

SyncOutput(Semaphore s, String m) {
    sem = s;
    msg = m;
}

public void run() {
    for (int i = 0; i < 3; i++){
        try {
            sem.acquire(1);
            System.out.println(msg + " : " + ++val);
            Thread.sleep(1000);
        } catch (Exception exc) {
            System.out.println("Error Writing File");
        }
    sem.release(1);
    }
}

}

第二種方式:-----

包線程;

 class num {
         // state variable identifying whose turn it is.
         private String whoseTurn ="A";
         private int cnt=0;

  public  boolean writenum(String who) {

           String x = Thread.currentThread().getName();
                try{
                    Thread.sleep(1000);
                }catch(Exception e){}
          if (x.equalsIgnoreCase(whoseTurn)) {
              System.out.println(x+":"+cnt++);
              if(x.equalsIgnoreCase("A"))
                whoseTurn = "B";
              else if(x.equalsIgnoreCase("B"))
                    whoseTurn = "C";
              else if( x.equalsIgnoreCase("C"))
                    whoseTurn = "D";
              else if( x.equalsIgnoreCase("D"))
                    whoseTurn = "A";

          }
          return true; 
     }
  }


public class Game {

    public static void main(String args[]) {
        num ob = new num();
        Thread A = new Thread(new Player("A", ob));
         Thread B   = new Thread(new Player("B", ob));
        Thread C   = new Thread(new Player("C", ob));
        Thread D   = new Thread(new Player("D", ob));

    A.setName("A");
    B.setName("B");
    C.setName("C");
    D.setName("D");
   A.start();   
   B.start();  
   C.start();
   D.start();
   try {
       // Wait 5 seconds
       Thread.currentThread().sleep(5000);
   } catch (InterruptedException e) { }

   ob.writenum("DONE"); // cause the players to quit their threads.
   try {
       Thread.currentThread().sleep(100);
   } catch (InterruptedException e) { }
   }

}

class Player implements Runnable {
       num area;   // Table where they play
       String who;

       public Player(String who, num area) {
           this.area  = area;
          this.who = who;
       }

      public void run() {
      while (area.writenum(who));

      }
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM