Thread nur bei Methodenaufruf ausführen

nchristoph

Erfahrenes Mitglied
Hallo,

ich versuche mich gerade in Threads und komme einfach nicht weiter.

Java:
  public void checkForItvDespawn(CreatureObject actor, SWGObject object){
     if(object == null){
       Thread.currentThread().interrupt();
       return;
     }       

     Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
       public void run() {
         try {
           if(object == null){
             Thread.currentThread().interrupt();
             return;
           }     
           if (actor.getPosition().getDistance2D(object.getPosition()) >= 50){
             core.objectService.destroyObject(object.getObjectID());
             actor.sendSystemMessage("@travel:pickup_cancel", DisplayType.Broadcast);
             Thread.currentThread().interrupt();
             return;
           }
           
           long oldtime = System.currentTimeMillis();
           
           if(System.currentTimeMillis() - oldtime >= 60000){
             core.objectService.destroyObject(object.getObjectID());
             actor.sendSystemMessage("@travel:pickup_timeout", DisplayType.Broadcast);
             Thread.currentThread().interrupt();
           }
           
         }catch (Exception e) {
           e.printStackTrace();
         }
       }
     }, 1, 10, TimeUnit.SECONDS);
     
     return;
   }

scheduleAtFixedRate läuft ja bis zum Sankt Nimmerleins Tag.

Ich suche jetzt eine möglichkeit, um einen Thread nur solange auszuführen, wie die Methode ausgeführt wird.

Geht sowas überhaupt in Java?

Momentan wird der Thread immer wieder von neuem ausgeführt anstatt nach der Zerstörung des Objects beendet zu werden.

Kann mir jemand helfen?
 

Harrier

Erfahrenes Mitglied
Ich bin mir nicht ganz sicher, was du hier tun willst, aber mal ein paar Dinge:
- scheduleAtFixedRate() erstellt dir die selbe Task immer wieder. Das scheint genau nicht das zu sein, was du willst. Mehr dazu unter
http://docs.oracle.com/javase/7/doc...e, long, long, java.util.concurrent.TimeUnit)
- Du interruptest öfters mal den Thread, der die run-Methode ausführt. Das wird aber jeweils nur dazu führen, dass dir der StackTrace ausgeben wird (du catch'st die Exception ja sofort wieder).
- Lies dir am Besten mal das Java-Tutorial zu Threads durch. Im Normalfall erstellst du einen Thread anders.
http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
Dann ist es auch ganz einfach. Der Thread ended sobald die run()-Methode des Runnable-Interfaces durchlaufen ist.

Viele Grüße
 

nchristoph

Erfahrenes Mitglied
Was ich will ist, das der thread beendet wird, sobald der actor 50 m vom object entfernt ist und das object zerstört ist.
 

Harrier

Erfahrenes Mitglied
Okay. Deine Abfrage hast du ja bereits. Was meinst du mit "das object zerstört ist"?

In jedem Fall wird die Methode (und damit auch der Thread) beendet, sobald du return; erreichst (oder das Ende der Methode). Den Interrupt kannst du dir sparen. (Die Zeile Thread.currentThread().interrupt(); führt nur dazu, dass eine Exception geworfen wird, die du sofort wieder auffängst und den Stack Trace ausgibst.) Diese Zeile also löschen!

Wenn dein Thread jetzt bis zum return; kommt, endet er. (Das tut er auch mit interrupt, aber es ist wie gesagt unnötig). Allerdings startest du alle 10 Sekunden wieder einen neuen Thread, der das Ganze nochmal macht. Du solltest dir http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html durchlesen, da wird beschrieben, wie man in Java ganz normal einen neuen Thread erstellt. Dieser wird dann auch nur einmal ausgeführt und hört auf, sobald er fertig ist.

scheduleAtFixedRate erstellt eben immer und immer wieder neue Threads.
 

nchristoph

Erfahrenes Mitglied
Das start wird in der Engine automatisch ausgeführt.

Ich habe jetzt mal den Code entsprechened den Tutorials, den vorlagen die ich habe und deinen Tips abgeändert.

Java:
public void checkForItvDespawn(CreatureObject actor, SWGObject object){
  ScheduleFuture<?> itvHandle = Executors.newScheduledThreadPool(1).schedule(new Runnable() {
  public void run() {
  try {
  if (actor.getPosition().getDistance2D(object.getPosition()) >= 50){
  core.objectService.destroyObject(object.getObjectID());
  actor.sendSystemMessage("@travel:pickup_cancel", DisplayType.Broadcast);
  }

  long oldtime = System.currentTimeMillis();

  if(System.currentTimeMillis() - oldtime >= 60000){
  core.objectService.destroyObject(object.getObjectID());
  actor.sendSystemMessage("@travel:pickup_timeout", DisplayType.Broadcast);
  }

  }catch (Exception e) {
  e.printStackTrace();
  }
  }
  }, 1, TimeUnit.SECONDS);

  }

Jetzt hab ich allerdings das problem, das der Thread gleich wegstartet, allerdings wird er nur einmal durchlaufen und dann wars das. Sollte ich den Funktionsaufruf im Python script vielleicht in ne while schleife packen?

Momentan wir die Funktion so aufgerufen:
Java:
def run(core, actor, object):
   core.travelService.checkForItvDespawn(actor, object)
   return;


/edit:
Ich habs hingekriegt. Ich hatte den Thread nur in der falschen Funktion angehängt gehabt.

Danke für die Tutoriallinks
 
Zuletzt bearbeitet: