0

Ich möchte Folgendes tun: 2 Thread führen die gleichen Runnable Objekt. Sie werden eine Zufallszahl generieren. Schreiben Sie die Nummer in das Protokoll. Wenn die Nummer durch 7 teilbar ist, stoppen Sie beide Threads und eine Broadcast-Nachricht wird gesendet und der Broadcast-Empfänger platziert die letzte Nummer im Log mit einem neuen Tag. Ich habe sowohl interrupt() und volatile versucht, aber aus irgendeinem Grund wird einer der beiden Thread eine zusätzliche Schleife vor dem Stopp laufen.Stoppen Sie zwei Threads, wenn die Bedingung erfüllen

public boolean onKeyDown(int keyCode, KeyEvent event) { 

    progDailog = ProgressDialog.show(this, "Progress dialog", 
      "Working....", true); 
    Thread one = new Thread(background, "first"); 
    one.start(); 

     Thread two = new Thread(background, "second"); 
     two.start(); 

    return true; 
}// 

    Runnable background = new Runnable() { 
     public void run() { 

       while (num1 % 7 != 0 && num % 7 != 0) { 

         try { 
          // just doing some long operation 
          Thread.sleep(1000); 
          Random rand = new Random(); 
          num = rand.nextInt(9000) + 1000; 
          name = Thread.currentThread().getName(); 
          tag = "before"; 
          Log.e(tag, name + ":" + num); 
          if (num % 7 == 0) { 
           num1 = num; 
          } 
         } catch (InterruptedException e) { 
         } finally { 
          handler.sendEmptyMessage(0); 
          progDailog.dismiss(); 
         } 
       } ; 
       Intent myObserverSender = new Intent(
         "action.GO"); 
       msg = name + ":" + num; 
       myObserverSender.putExtra("serviceData", msg); 
      sendBroadcast(myObserverSender); 
     } 

    }; 

public class MyMainLocalReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context localContext, Intent callerIntent) { 
     String serviceData = callerIntent.getStringExtra("serviceData"); 
     tag = "after"; 
     Log.e (tag, serviceData); 
    } 
} 

Hier Endergebnis ist

before: first:7877 

before: second:9165 

before: first:6760 

before: second:5663 

After: second:5663 <<<< should stop here 

before: first:8025 >>>> this's the extra loop 

After: first:5663 >>> wrong 

By the way, habe ich getan die Sendung richtig?

+0

Ist das vollständige Code? Ich kann keinen Code sehen, um den Thread zu beenden. – Aakash

+0

und ... setzen Sie ein ';' an der Endung '}' von while ...? – sharan

+0

Total erwartet. Sie "sync" beide Thread "einmal in der Weile" (Wortspiel beabsichtigt), dass Sie überprüfen, Num1 durch 7 teilbar sein. Wenn beide von ihnen irgendwo innerhalb der while sind, werden beide ihren Zyklus beenden. Wenn Sie nicht möchten, dass der "spätere" Thread ein Ergebnis von "früherem" Thread überschreibt, müssten Sie noch einmal überprüfen, bevor Sie num1 ... setzen. – Fildor

Antwort

0

Ich erstellte eine vereinfachte Version des Stoppen der Threads. So funktioniert es:

  1. Der Hauptthread erstellt einen Befehl, der die anderen Threads stoppt.
  2. Die wichtigsten Themen speichert die Verweise auf die Gewinde
  3. Der Haupt-Thread gibt den Stopper-Befehl an die Fäden angehalten werden, damit sie es, wenn
  4. Der Stopper Befehl verwendet einen AtomicBoolean, um sicherzustellen, benötigt nennen es die Anschläge problematische Threads nur einmal.
  5. Ich piggy-backed die Thread-Stop-Logik auf der interrupt() Methode.

So, hier ist der vollständige Code:

package com.example; 

import java.util.List; 
import java.util.Random; 
import java.util.concurrent.CopyOnWriteArrayList; 
import java.util.concurrent.atomic.AtomicBoolean; 

public class Main { 

    public static void main(String[] args) { 
     final List<Thread> threads = new CopyOnWriteArrayList<>(); 
     final AtomicBoolean stopping = new AtomicBoolean(false); 
     Runnable stopCommand =() -> { 
      if (!stopping.getAndSet(true)) { 
       for (Thread thread : threads) { 
         thread.interrupt(); 
       } 
      } 
     }; 
     Background background = new Background(stopCommand); 
     Thread t1 = new Thread(background); 
     Thread t2 = new Thread(background); 
     threads.add(t1); 
     threads.add(t2); 
     t1.start(); 
     t2.start(); 

    } 

    private static class Background implements Runnable { 

     private Runnable stopCommand; 

     public Background(Runnable stopCommand) { 
      this.stopCommand = stopCommand; 
     } 

     @Override 
     public void run() { 
      Random rand = new Random(); 
      String name = Thread.currentThread().getName(); 
      while (!Thread.currentThread().isInterrupted()) { 
       int num = rand.nextInt(9000) + 1000; 
       System.out.println(name + ", num: " + num); 
       if ((num % 7) == 0) { 
        stopCommand.run(); 
       } 
      } 
      System.out.println(name + " interrupted. Stopping."); 
     } 

    } 

} 

Statt eine Liste mit sich selbst, können Sie auch Testamentsvollstrecker verwenden:

package com.example; 

import java.util.Random; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class Main { 

    public static void main(String[] args) { 
     final ExecutorService ex = Executors.newFixedThreadPool(2); 
     Runnable stopCommand =() -> { 
      System.out.println("stopping"); 
      ex.shutdownNow(); 
     }; 
     Background background = new Background(stopCommand); 
     ex.submit(background); 
     ex.submit(background); 
    } 

    private static class Background implements Runnable { 

     private Runnable stopCommand; 

     public Background(Runnable stopCommand) { 
      this.stopCommand = stopCommand; 
     } 

     @Override 
     public void run() { 
      Random rand = new Random(); 
      String name = Thread.currentThread().getName(); 
      while (!Thread.currentThread().isInterrupted()) { 
       int num = rand.nextInt(9000) + 1000; 
       System.out.println(name + ", num: " + num); 
       if ((num % 7) == 0) { 
        stopCommand.run(); 
       } 
      } 
      System.out.println(name + " interrupted. Stopping."); 
     } 

    } 

} 
Verwandte Themen