2016-04-15 9 views
2

Ich habe ein Haupt-Thread und ein Worker-Thread. Der Haupt-Thread fügt Aufgaben in eine Warteschlange ein, und der Worker-Thread nimmt sie zur Berechnung von Daten auf. Bevor ich die Objekte in die Warteschlange bringe, rufe ich ein ReentrantLock-Objekt (im Haupt-Thread) innerhalb der Aufgabenobjekte auf. Wenn der Arbeitsthread mit der Bearbeitung einer Aufgabe aus der Warteschlange fertig ist, rufe ich die Entsperrung auf (im Worker-Thread). Das Problem ist, dass ich eine IllegalMonitorStateException bekomme, weil ich Sperren und Entsperren auf verschiedenen Threads aufrufen.Java lock und entsperren auf anderen Thread

Ich bin auf der Suche nach einem alternativen Schloss-System, wo ich dies auf verschiedenen Threads tun kann.

Beispiel:

public class Worker extends Thread { 
    public static Queue<Task> tasks = new ConcurrentLinkedQueue<Task>(); 

    @Override 
    public void run() { 
     while (true) { 
      Task task = tasks.poll(); 

      if (task != null) { 
       task.work(); 
       task.lock.unlock(); // Here is the unlock, Task#i should not change up to now 
      } 
     } 
    } 
} 


public class Task { 
    private int i = 0; 
    public Lock lock; 

    public void setI(int i) { 
     lock.lock(); 
     this.i = i; 
     lock.unlock(); 
    } 

    public void work() { 
     System.out.println(i); 
    } 
} 


public class Test { 
    Task task = new Task(); 

    public void addTask() { 
     task.lock.lock(); // Here is the lock, Task#i should not change 
     Worker.tasks.add(task); 
    } 
} 
+0

Was möchten Sie mit Ihrem Schloss schützen? – Savior

+0

@Pillar Daten in den Objekten. – stonar96

+0

synchronisieren auf dem Objekt vor dem Sperren und Entsperren – ControlAltDel

Antwort

1

Warum nicht eine Semaphore mit nur einer Genehmigung verwenden? Anstelle der Sperroperation erhalten Sie die Einzelgenehmigung. Sie sollten die Sperre immer mit der Freigabe() freigeben.

0

Gemäß der Frage, Es ist nicht richtig aussieht Multi-Threaded-Anwendung zu entwerfen.

Entweder Worker-Thread sollte die Erstellung von Objekt behandeln oder Sie sollten unveränderliches Objekt an Worker-Thread übergeben und sobald Worker-Thread beendet ist, kann es Ergebnis zurück zum Hauptthread übergeben.

Ich denke nicht, dass es possible ist, Sperre in einem Thread zu erwerben und in einem anderen entsperren.

+0

Ich kann die Anwendung nicht neu gestalten. Ich ändere eine Anwendung. Die ursprüngliche Anwendung ist single-threaded und ich möchte diesen Arbeitsthread hinzufügen, der mit dem Status eines Objekts zu der Zeit arbeiten sollte, als es der Warteschlange hinzugefügt wurde. – stonar96

0

Sie benötigen kein alternatives Verriegelungssystem. Die ConcurrentLinkedQueue Datenstruktur bietet bereits ein eigenes Lock-System und garantiert Thread-Sicherheit. Eine zusätzliche Verriegelung ist nicht erforderlich.

Aber Sie erfinden das Rad hier neu. Ich empfehle Ihnen einen Blick auf ExecutorService und ThreadPools. Während es eine gute Lernerfahrung ist, Dinge selbst zu bauen. Es ist auch eine große Quelle von Fehlern.