2017-06-07 4 views
0

In dieser Übung versuchen wir, einen Codeblock zu synchronisieren. Innerhalb dieses Codeblocks erhalten wir die Sperre für ein Objekt, sodass andere Threads es nicht ändern können, während der Codeblock ausgeführt wird. Wir werden drei Threads erstellen, die alle versuchen, dasselbe Objekt zu manipulieren. Jeder Thread gibt 100 Mal einen einzelnen Buchstaben aus und erhöht diesen Buchstaben dann um eins. Das Objekt, das wir verwenden werden, ist StringBuffer. Wir könnten für ein String-Objekt synchronisieren, aber Zeichenfolgen können nicht geändert werden, sobald sie erstellt wurden, so dass wir den Buchstaben nicht erhöhen könnten, ohne ein neues String-Objekt zu erzeugen. Die endgültige Ausgabe sollte 100 A's, 100 B's und 100 C's haben, alle in durchgezogenen Linien.Synchronisieren eines Codeblocks - Übung 13-2

  1. Erstellen Sie eine Klasse und erweitern Sie die Thread-Klasse.

  2. Die run() -Methode von Thread überschreiben. Hier wird der synchronisierte Codeblock ausgeführt.

  3. Damit unsere drei Thread-Objekte dasselbe Objekt verwenden können, müssen wir einen Konstruktor erstellen, der ein StringBuffer-Objekt im Argument akzeptiert.

  4. Der synchronisierte Codeblock wird eine Sperre für das Objekt aus Schritt erhalten Stringbuffer 3.

  5. Innerhalb des Blocks ausgegeben, um die Stringbuffer 100 mal und dann den Brief in den Stringbuffer inkrementieren. Sie können Kapitel 5 für StringBuffer (StringBuilder) -Methoden überprüfen, die dabei helfen.

  6. Schließlich, in der main() -Methode, erstellen Sie ein einzelnes StringBuffer-Objekt mit dem Buchstaben A, dann erstellen Sie drei Instanzen unserer Klasse und starten Sie alle drei von ihnen.

Lösung:

public class OCJPThread Thema erweitert {

StringBuffer sb; 
public OCJPThread(StringBuffer sb) { 
    this.sb =sb; 
} 


public void run(){ 
    synchronized (sb) { 
     System.out.println(Thread.currentThread().getName()); 
     for(int i=1;i<=100;i++) 
      System.out.print(sb); 

     System.out.println(); 
     sb.setCharAt(0, (char)(sb.charAt(0)+1)); 


    } 
} 

public static void main(String[] args) { 
    StringBuffer sb = new StringBuffer("A"); 
    OCJPThread t1 =new OCJPThread(sb); 
    OCJPThread t2 =new OCJPThread(sb); 
    OCJPThread t3 =new OCJPThread(sb); 

    t1.start(); 
    t2.start(); 
    t3.start(); 
} 

} Ausgang Gewinde 0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Thema-2 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB Gewinde-1 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

Frage: Wenn ich String oder String verwende, spielt es keine Rolle, wie ich syncronized Block verwenden.

Aber wenn ich synchronisiert (this) anstelle von Stringbuffer-Objekt verwenden. Die Ausgabe ist nicht vorhersagbar. Da String-Puffer bereits synchronisiert sind, warum müssen wir es selbst tun?

Antwort

0

StringBuffer wird synchronisiert, aber nur bei jedem einzelnen Methodenaufruf. Dies bedeutet, dass der Teil, der den Wert des Zeichenfolgenpuffers ausgibt, nicht in einem synchronisierten Block ausgeführt wird, wenn Sie keine Synchronisation verwenden. Einer der anderen Threads kann den Puffer während dieser Zeit aktualisieren. Wenn dies geschieht, zeigt der Ausdruck den neuen Wert an.Sie können nicht wirklich wissen, welcher Thread den Puffer zuerst aktualisiert.

Außerdem kann ein Thread den Wert zwischen dem Aufruf an sb.charAt() und dem Aufruf an sb.setCharAt() ändern. Daher kann das Ergebnis des Inkrements selbst unvorhersehbar sein.

Hinweis: Synchronisieren auf this bedeutet, dass jeder Thread auf eine andere Sperre synchronisiert, so ist es wie überhaupt nicht zu synchronisieren.

1

Sie geben die gleiche Referenz an alle drei Threads weiter. Wenn sie sich darauf synchronisieren, können sie alle gleichzeitig in die StringBuffer schreiben. Wenn sie auf dem gemeinsamen StringBuffer synchronisieren, kann nur ein Thread auf sie gleichzeitig zugreifen.