2016-05-18 10 views
1

Ich habe einfache Klasse, das ist erweitert Thread-Klasse es Methode, die wie folgt aussieht laufen hat:Wie zu bestimmen, ob Thread eine Aktion tut

public void run() { 

    while(running) { 

     if(enabled) 
     { 
      doStep(); 
      enabled = false; 
     } 
     else 
     { 
      try { 
       this.sleep(1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

In anderen Platz in meinem Code, den ich anrufen, wenn ich will myObject nennen doStep()

myObject.enbled = true; 

Aber wie kann ich sicherstellen, dass myObject tatsächlich doStep() Verfahren beendet hat?

einfach
myObject.enable = true 
while(myObject.isEnabled()) 
{ 
; 
} 
doActionAfterObjectFinish(); 

irgendwann Programm zu stecken verursachen in der Schleife, und sicher doStep() es nicht verursachen.

@danke für Antworten anstelle von sempahores woudlnt es hilft, wenn ich Code auf solche Weise ändern?

public void run() { 

     while(running) { 

      if(enabled) 
      { 
       synchronized(this){ 
       doStep(); 
       enabled = false; 
} 
      } 
      else 
      { 
       try { 
        this.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

public synchronized boolean isEnabled() { 
return enabled; 
} 
+0

Eine erste Idee, einen Zähler hinzuzufügen wäre, die zählt, wie oft doStep() ausgeführt wurde. Fügen Sie Zähler ++ unterhalb der DoStep-Methode hinzu. Dann können Sie den Zähler ln äußere while wie myObject.getRuntimes()> 0 abfragen. – mstrewe

Antwort

3

One, stellen Sie sicher, dass die myObject.enable Variable als volatile deklariert wird.

Zwei, schlage ich für java.util.concurrent Paket zu verwenden, was Sie versuchen ... zu modellieren kann ein Semaphore Ihnen helfen kann ...

import java.util.concurrent.Semaphore; 

public class Example { 

    public static void main(String[] args) throws InterruptedException { 
    MyRunnable target = new MyRunnable(); 
    Thread thread2 = new Thread(target); 

    thread2.start(); 
    target.waitUntilFinish(); 

    System.out.println("MyRunnable ends first!"); 
    } 


    public static class MyRunnable implements Runnable { 

    private Semaphore workDone = new Semaphore(0); 
    private int count; 

    @Override 
    public void run() { 
     while (true) { 
      // heavy work here... 
      if (this.count < 5) { 
       System.out.println("Iteration: " + (++this.count)); 
      } else { 
       this.workDone.release(); 
       break; 
      } 
      try { Thread.sleep(2000L); } catch (InterruptedException ex) { } 
     } 
    } 

    public void waitUntilFinish() throws InterruptedException { 
     this.workDone.acquire(); 
    } 
    } 
} 
+0

Shoudl meine Klasse, die 'my.Object.isenaled()' 'hat Zugriff auf Semaphore, die innerhalb 'myObject' sein würde? – whd

+0

Ja ... Ich bearbeite meine Antwort, um ein Beispiel hinzuzufügen ... –

+0

Danke für die Antwort und Beispiel! Ich akzeptiere es, wenn du so nett bist und überprüfe, ob mein bearbeiteter Code, der 'synchronisierte' verwendet, nicht auf die gleiche Weise funktioniert? – whd

0

Wenn Sie mit Multithreading auf CPU wird dringend empfohlen, Verwenden Sie Semaphore oder Sperren. Werfen Sie einen Blick darauf: A java's aproach to Spinlocks und Oracle documentation of semaphores. Im Wesentlichen müssen Sie einen Semaphor oder Spinlock setzen, um den Code zu sperren, wenn Sie ihn benötigen, und ihn entsperren, wenn er benötigt wird. Ist eine gemeinsame und sehr empfehlenswerte Praxis zu nehmen.

Ein Pseudo-Code aproach von Spinlocks, die für Sie nützlich sein könnte, ist:

void thread1(){ 
    while(true){ 
     while(locked(lock1)); 

     lock(lock2); 
     doActions(); 
     unlock(lock2); 
    } 
} 

void thread2(){ 
    while(true){ 
     while(locked(spinlock2)); 

     lock(spinlock1); 
     doStuff(); 
     unlock(spinlock1); 
    } 

} 
Verwandte Themen