2015-08-10 5 views
7

In Android Studio habe ich einen Thread in einer Methode wie folgt enthalten (siehe unten), weil ich möchte den Thread neu starten, wenn es [1] aufgerufen wird, (neu erstellen Gewinde anstatt Neustart)Android: Interrupt-Thread in einer Methode enthalten

public void callthread(){ 

    final Thread myThread = new Thread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      for (int x=0; x<750&&!Thread.interrupted(); x++) { 
       //using this and thread sleep for repeated timed code within a thread 

       try { 
        Thread.sleep(4); 
        runOnUiThread(new Runnable() 
        { 
         @Override 
         public void run() { 

          //some code 

          if (condition) {  
           myThread.interrupt(); 
          } 
         } 
        }); 

       } catch (InterruptedException e) { 

       } 
      } 
     } 
    }); 

Mein Problem ist, dass es mich nicht myThread.interrupt(); an der gewünschten Stelle in meinem Code verwenden lassen, mir einen Fehler geben sagen: „Variable‚myThread‘wurde möglicherweise nicht initialisiert“ und wird nicht kompiliert aus diesem Grund. Es funktioniert jedoch, wenn der gesamte Thread in der Klasse enthalten ist, aber ich habe keine Möglichkeit, es neu zu starten. Mit anderen Worten, Ich brauche eine Möglichkeit, den Thread zu unterbrechen, während er in einer Methode enthalten ist. [2]

akzeptierte Lösungen

[1]. Eine Lösung, bei der der Thread neu gestartet werden kann

[2]. Eine Lösung, bei der der Faden unterbrochen werden kann, während der Faden in einem Verfahren enthalten ist

PS: Wenn sein unklar, ich habe meinen Code oben für eine gute Lesbarkeit bearbeitet, aber ich habe nicht Dinge wie die for Schleife oder die Thread.sleep entfernt Ich nehme an, sie könnten Teil des Problems sein. Also, wenn Theres zu viele oder zu wenig von einer bestimmten geschweifte Klammer das ist dann nicht das Problem

EDIT: Gesuchter um und anscheinend kann nicht Neustart ein Thread

+0

'unterbrochen' ist nutzlos. vor allem, wenn Sie es aus dem Thread heraus aufrufen. Nur 'zurück' aus dem Lauf und der Thread stoppt. Java lässt Sie 'myThread' hier nicht verwenden, weil es nicht weiß, dass der' run' erst aufgerufen wird, nachdem die Initialisierungsphase abgeschlossen ist und die Variable tatsächlich einen Wert hat. aber sowieso brauchst du es nicht. – njzk2

+1

Verwenden Sie auch 'wait' +' notify' anstelle von 'sleep' + 'interrupt' – njzk2

+0

' für (int x = 0; x <750; x ++) { versuchen { Thread.sleep (4); runOnUiThread (neu Runnable() { @Override public void run() { // vage Bildansicht x +1 if (true) { return; } } }); } ' vage Bild Ansicht bewegt sich nach wie vor richtig (es sei denn, ich benachrichtigen müssen + warten, bis es zu arbeiten, obwohl im nur Interrupt mit dem Thread zu beenden) in der Programmiersprache Java tun – Mazino

Antwort

2

Sie können die Unterbrechung Thread in myThread starten, bevor die for-Schleife eingeben. Der unterbrechende Thread schläft 5 Sekunden und unterbricht dann myThread. Der Interrupt wird im Ausnahmebehandler behandelt. Dort wird die Schleifenvariable x auf 0 zurückgesetzt, was praktisch ein Neustart der Schleife ist.

public class ThreadInterruptRestart { 

    public static void main(String[] args) { 
     new ThreadInterruptRestart().callthread(); 
    } 

    public void callthread() { 

     final Thread myThread = new Thread("myThread") { 
      @Override 
      public void run() { 
       final Thread _this = this; 

       Thread interruptingThread = new Thread(new Runnable() { 
        @Override 
        public void run() { 
         try { 
          Thread.sleep(5000); 
         } catch (InterruptedException e) { 
          // this is not the interrupt we are interested in 
          e.printStackTrace(); 
         } 
         if (true) { 
          System.out.println("interrupting " + _this + " from thread " + this); 
          _this.interrupt(); 
         } 
        } 
       }, "interrupting thread"); 
       interruptingThread.start(); 

       for (int x = 0; x < 750; x++) { 
        // using this and thread sleep for repeated timed code 
        // within a thread 
        try { 
         System.out.println(x); 
         Thread.sleep(10); 
        } catch (InterruptedException e1) { 
         // this is the interrupt we want to handle 
         System.out.println("" + this + " interrupted!"); 
         // reset the loop counter 
         x = 0; 
        } 
       } 
      } 
     }; 
     myThread.start(); 
    } 
} 

Und eine andere Version, wo myThread schläft nicht, und die Synchronisation wird anstelle eines InterruptedException verwendet:

public class ThreadInterruptRestart { 

    public static void main(String[] args) { 
     new ThreadInterruptRestart().callthread(); 
    } 

    public void callthread() { 

     final Object mutex = new Object(); 

     final Thread myThread = new Thread("myThread") { 
      @Override 
      public void run() { 
       final Thread _this = this; 

       Thread interruptingThread = new Thread(new Runnable() { 
        @Override 
        public void run() { 
         try { 
          Thread.sleep(1); 
         } catch (InterruptedException e) { 
          // this is not the interrupt we are interested in 
          e.printStackTrace(); 
         } 
         if (true) { 
          System.out.println("interrupting " + _this + " from thread " + this); 
          synchronized (mutex) { 
           _this.interrupt(); 
          } 
         } 
        } 
       }, "interrupting thread"); 
       interruptingThread.start(); 

       for (int x = 0; x < 75000; x++) { 
        // using this and thread sleep for repeated timed code 
        // within a thread 
        synchronized (mutex) { 
         System.out.println(x); 
         // do other stuff here 
        } 
        if (Thread.interrupted()) { 
         // this is the interrupt we want to handle 
         System.out.println("" + this + " interrupted!"); 
         // reset the loop counter 
         x = 0; 
        } 
       } 
      } 
     }; 
     myThread.start(); 
    } 
} 
1

Es gibt bessere Möglichkeiten, den Thread zu beenden. Allerdings, wenn Sie das Gewinde für den Zugriff auf eine Referenzgröße wie folgt verwenden:

public void callthread(){ 

    final Thread myThread = new Thread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      final Thread _this = this; 
      for (int x=0; x<750&&!Thread.interrupted(); x++) { 
       //using this and thread sleep for repeated timed code within a thread 

       try { 
        Thread.sleep(4); 
        runOnUiThread(new Runnable() 
        { 
         @Override 
         public void run() { 

          //some code 

          if (condition) {  
           _this.interrupt(); 
          } 
         } 
        }); 

       } catch (InterruptedException e) { 

       } 
      } 
     } 
    }); 
+0

noch nicht lassen Sie mich neu starten: / – Mazino

1

Der Fehler im Code ist „Leaking dieser Konstruktor“, wo Sie versuchen, die anrufen Objekt (in Ihrem Fall) Thread-Methode, bevor der Thread instanziiert wurde.

Um das zu lösen Sie für ein Design ähnlich dem Observer-Muster

1

Ist dies irgend gehen kann?

Als eine Randnotiz ist runOnUiThread ziemlich ein Code-Geruch und kann zu einigen ziemlich subtilen Timing-Bugs führen. Wofür verwenden Sie es? Es ist auch sehr schwer zu sagen, was Sie hier erreichen wollen. Etwas wie einen Executor zu verwenden, kann die Dinge erheblich vereinfachen.

public void callthread() 
{ 

    final Thread myThread = new Thread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      final Thread thread = Thread.currentThread(); 
      for (int x = 0; x < 750 && !Thread.interrupted(); x++) 
      { 
       //using this and thread sleep for repeated timed code within a thread 

       try 
       { 
        Thread.sleep(4); 
        runOnUiThread(new Runnable() 
        { 
         @Override 
         public void run() 
         { 

          //some code 

          if (true) 
          { 
           thread.interrupt(); 
          } 
         } 
        }); 

       } 
       catch (InterruptedException e) 
       { 

       } 
      } 
     } 
    }); 
} 
0

Ein Teil des Problems ist, dass Sie in verschachtelten Aufgabenklassen verloren gehen.Ein anderer Teil besteht darin, dass Sie zu sehr versuchen, den Threading-Mechanismus zu verwenden, um Ihre logische Kontrolle zu übernehmen. Lassen Sie Ihre Klassen also selbst steuern und halten Sie Ihr Threading-Modell einfach.

ParallelTask

/** 
* An implementation of your inner Runnable. 
*/ 
public class ParallelTask implements Runnable 
{ 
    protected ParallelTaskRunner m_runner = null ; 

    private ParallelTask() {} // Disallow default constructor. 

    public ParallelTask(ParallelTaskRunner runner) 
    { m_runner = runner ; } 

    @Override 
    public void run() 
    { 
     // The code from that original inner class. 
     if(/* trigger condition */) 
      m_runner.stop(this) ; 
    } 
} 

ParallelTaskRunner

/** 
* An implementation of the outer class. 
*/ 
public class ParallelTaskRunner implements Runnable 
{ 
    public static final int THREAD_COUNT = 750 ; 

    protected boolean m_bRunning = false ; 
    protected ParallelTask m_tskStopper = null ; 

    @Override 
    public void run() 
    { 
     if(m_bRunning) return ; // Don't run if already running. 
     m_bRunning = true ; m_tskStopper = null ; 
     for(int i = 0 ; i < THREAD_COUNT && m_bRunning ; i++) 
     { 
      try 
      { 
       // Insert some wait interval here if desired. 
       (new Thread(new ParallelTask(this))).run() ; 
      } 
      catch(Exception x) 
      { 
       Log.w("ParallelTaskRunner.run()", 
         "Caught exception.", x) ; 
      } 
     } 
    } 

    public synchronized void stop(ParallelTask tsk) 
    { 
     m_bRunning = false ; 
     if(m_tskStopper == null) 
      m_tskStopper = tsk ; 
    } 

    public ParallelTask getStopper() 
    { return m_tskStopper ; } 
} 
Und dann, in einigen Consumer-Klasse ...
public void callThreads() 
{ 
    ParallelTaskRunner runner = new ParallelTaskRunner() ; 
    (new Thread(runner)).run() ; 
} 

In der 012.Methode können Sie dann Berichte basierend auf den in runner enthaltenen Daten anzeigen. Wenn sich die Threads beispielsweise eindeutig mit einer UUID oder einer einfachen Ganzzahl (dem Index der Schleife?) Identifizieren, könnte Ihre Anwendung einen Toast mit der ID der Task "Stopper" anzeigen. Wenn der Code, den Sie in ParallelTask ausführen, interessante Daten ausgibt, dann können diese Daten durch Zugriffsmethoden in ParallelTask zur Verfügung gestellt werden, die Sie dann aufrufen würden, indem Sie zuerst runner.getStopper() aufrufen und dann auf der ParallelTask Instanz arbeiten.

Verwandte Themen