2016-11-12 2 views
0

Ich versuche, etwas Ähnliches zu implementieren- Eine Singleton-Klasse halten einige Objekte des Typs Thread (Klassenzimmer mit 2 Studentenobjekte) und es existiert eine Klasse, die einige statische Ressource (Resource.java) enthält . Ich starte die 2 Threads in meiner Singleton-Klasse nacheinander und lasse sie die statische Ressource konsumieren. Dies geschieht in einer synchronisierten Methode der Klasse, die Ressourcen hat. In der run-Methode des Fadens, nenne ich die oben synchronisierte Methode und erhalte Ausgabe als unten-Implementieren von freigegebenen Ressourcen Algo mit Singleton und Multithreading

Output-

Antrag auf Schokolade ab: 0
prüfen, ob andere Childs vorhanden: Ja
Block endet
--Student 0 beendet laufen ---
Antrag auf Schokolade aus: 1
überprüfen, ob andere childs vorhanden: Ja
Block
endet--Student 1 beendet den Lauf! ---

Meine Frage ist, dass nachdem child_1 die Ausführung des synchronisierten Blocks beendet und sleep() ausführt (thread_1 schläft für 5 sec und thread_2 für 0 sec), der andere Thread (child_2) sollte die Ausführung des synchronisierten Blocks beginnen, bevor child_1 aufwacht, weil child_1 nicht im synchronisierten Block und Ruhezeit von child_1 ist> dann die Ausführungszeit von child_2. WARUM blockiert child_1 den anderen?

Output-
Antrag auf Schokolade erwartet ab: 0
prüfen, ob andere Childs vorhanden: Ja
Block
Antrag auf Schokolade endet von: 1
überprüfen, ob andere Childs vorhanden: Ja
Block Enden
--Student 1 Oberflächen laufen! ---
--Student 0 beendet laufen! ---

Wie erreiche ich das?

Mein Code file-- Singleton-Klasse (ClassRoom.java)

public class ClassRoom { 

private static ClassRoom instance = null; 
private static Student s[]; 

public static ClassRoom getInstance() { 
    if (instance == null) { 
     instance = new ClassRoom(); 
     initStudents(); 
    } 
    return instance; 
} 

private static void initStudents() { 
    s= new Student[2]; 
    s[0] = new Student(0,2,5); 
    s[1] = new Student(1,2,5); 
} 

public Student getStudent(int i) { 
    return s[i]; 
} 
} 

Student.java

public class Student extends Thread { 
int sid; 
int max_choco; 
int allo_choco; 
private Resource resource= new Resource(); 

public Student(int i, int j , int k) { 
    sid = i; 
    allo_choco = j; 
    max_choco = k; 
} 

@Override 
public void run() { 
    try { 
     resource.requestChocolate(sid, 2); 
     Thread.sleep(Math.abs(1-sid)*5000); 
     System.out.println("--Student "+sid+" finishes run!--- "); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 
public int getSid() { return sid;} 

@Override 
public String toString() { 
    return sid+" : "+allo_choco+" : "+max_choco; 
} 
} 

Resource.java

public class Resource { 

private static int total_chocolate = 10; 

public void requestChocolate(int id, int request) { 
    synchronized (Student.class) { 
     System.out.println("Request for chocolate from : "+ 
          ClassRoom.getInstance().getStudent(id).getSid()); 
     if(request <= total_chocolate) { 
      System.out.println("check if other childs available: " 
      +((ClassRoom.getInstance().getStudent((id+1)%2).getSid()>-1 
      && ClassRoom.getInstance().getStudent((id+1)%2).getSid()<3)?"Yes":"No")); { 
      } 
      total_chocolate-=request; 
     System.out.println("block ends"); 
     } else { 
      System.out.println("Request cannot be granted"); 
     } 
    } 
} 
} 

Runner-Klasse (Test.java)

public class Test { 

public static void main(String args[]) { 
    ClassRoom room = ClassRoom.getInstance(); 
    for(int i = 0 ; i< 2; i++) { 
     room.getStudent(i).run(); 
    } 
} 
} 

Antwort

1

Sie sind nicht Starten der Thread richtig. Ihr Anruf an run() ist so synchron wie möglich :). Ändern Sie es so und es wird funktionieren:

ClassRoom room = ClassRoom.getInstance(); 
for(int i = 0 ; i< 2; i++) { 
     room.getStudent(i).start(); 
} 

Was passieren wird start() durch den Aufruf ist, dass die JVM einen neuen Thread erzeugen und dann rufen Sie die run() Methode in diesem Thread.Offensichtlich, da Sie run() überschreiben, bedeutet das, dass Ihr Code ausgeführt wird. Der Unterschied ist, dass wenn Sie run() direkt anrufen, dann ist die ganze Magie in start() verloren und der Aufruf wird im selben Thread ausgeführt, wie es durch den Aufruf einer anderen Methode geschehen wäre.

Einige andere mögliche Fehler:

  • In dieser Situation ist wünschenswert Student implementieren Runnable statt erstreckt Thread zu machen. Machen Sie eine Google-Suche, um zu verstehen, warum.
  • Ihr ClassRoom Singleton ist nicht Thread-sicher, was später Fehler verursachen könnte, wenn Sie nicht garantieren können, dass nur ein Thread ClassRoom verwendet. Fügen Sie die Synchronisation zu getInstance hinzu.
+0

Ich machte einen Aufruf zu run() anstelle von start(), der das Problem verursachte. Ich habe es korrigiert und das Programm funktioniert. Danke, Mann!!!! Ich verbrachte eine lange Zeit herauszufinden, warum es nicht funktionierte ..... Nochmals vielen Dank! –

Verwandte Themen