2014-04-19 1 views
3

J'essaie de comprendre comment je peux suivre tous les threads générés par mon application. Au début, je pensais que je l'avais compris à l'aide d'un CyclicBarrier, mais je vois des threads en cours d'exécution après mon appel d'attente.Suivi des threads d'exécution

Voici le code pseudo travail:

public class ThreadTesterRunner { 

    public static void main(String[] args) throws InterruptedException { 

     final CyclicBarrier cb = new CyclicBarrier(1); 
     ThreadRunner tr = new ThreadRunner(cb); 
     Thread t = new Thread(tr, "Thread Runner"); 
     t.start(); 

     boolean process = true; 
     // wait until all threads process, then print reports 
     while (process){ 
      if(tr.getIsFinished()){ 
       System.out.println("Print metrics"); 
       process = false; 
      } 
      Thread.sleep(1000); 
     } 
    } 
} 


class ThreadRunner implements Runnable { 
    static int timeOutTime = 2; 
    private ExecutorService executorService = Executors.newFixedThreadPool(10); 
    private final CyclicBarrier barrier; 
    private boolean isFinished=false; 

    public ThreadRunner(CyclicBarrier cb) { 
     this.barrier = cb; 
    } 

    public void run(){ 
     try { 
      boolean stillLoop = true; int i = 0; 
      while (stillLoop){ 
       int size; 
       Future<Integer> future = null; 
       try { 
        future = executorService.submit(new Reader()); // sleeps 
        size = future.get(); 
       } catch (InterruptedException | ExecutionException ex) { 
        // handle Errs 
       } 

       if(i == 3){ 
        stillLoop = false; 
        this.barrier.await(); 
        this.isFinished=true; 
       } 
       //System.out.println("i = "+i+" Size is: "+size+"\r"); 
       i++; 
      } 
     } catch (InterruptedException | BrokenBarrierException e1) { 
      e1.printStackTrace(); 
     } 
    } 

    public boolean getIsFinished(){ 
     return this.isFinished; 
    } 
} 

class Reader implements Callable { 
    private ExecutorService executorService = Executors.newFixedThreadPool(1); 

    @Override 
    public Object call() throws Exception { 
     System.out.println("Reading..."); 
     Thread.sleep(2000); 
     executorService.submit(new Writer()); 
     return 1000; 
    } 
} 

class Writer implements Callable { 
    @Override 
    public Void call() throws Exception { 
     Thread.sleep(4000); 
     System.out.println("Wrote");  
     return null; 
    } 
} 

Quelqu'un peut-il suggérer un moyen d'imprimer seulement « des mesures d'impression » après toutes les discussions ont exécuté?

Répondre

1

Il ne semble pas que vous faites quoi que ce soit pour coordonner avec votre Reader et Writer threads, qui sont ceux que vous voulez attendre. Si vous passez votre barrière de synchronisation à ces threads afin qu'ils puissent s'enregistrer et signaler quand ils sont terminés, cela fonctionne très bien.

est ici une version réécrite de le faire, en utilisant un Phaser au lieu d'un CyclicBarrier. Notez que chaque registre Reader et Writer lui-même sur la construction et la barrière de notifie la synchronisation lorsqu'il est fait exécuter:

public class ThreadTesterRunner { 
    public static void main(String[] args) throws InterruptedException { 
     final Phaser cb = new Phaser(); 
     ThreadRunner tr = new ThreadRunner(cb); 
     Thread t = new Thread(tr, "Thread Runner"); 
     t.start(); 

     boolean process = true; 
     // wait until all threads process, then print reports 
     while (process){ 
      if(tr.getIsFinished()){ 
       System.out.println("Print metrics"); 
       process = false; 
      } 
      //else { 
      // System.out.println("Waiting: registered=" + cb.getRegisteredParties() + ", arrived=" + cb.getArrivedParties() + ", unarrived=" + cb.getUnarrivedParties()); 
      //} 
      Thread.sleep(1000); 
     } 
    } 
} 


class ThreadRunner implements Runnable { 
    static int timeOutTime = 2; 
    private ExecutorService executorService = Executors.newFixedThreadPool(10); 
    private final Phaser barrier; 
    private boolean isFinished=false; 

    public ThreadRunner(Phaser phaser) { 
     this.barrier = phaser; 
    } 

    public void run(){ 
     try { 
      boolean stillLoop = true; int i = 0; 
      while (stillLoop){ 
       int size; 
       Future<Integer> future = null; 
       try { 
        future = executorService.submit(new Reader(this.barrier)); // sleeps 
        size = future.get(); 
       } catch (InterruptedException | ExecutionException ex) { 
        // handle Errs 
       } 

       if(i == 3){ 
        stillLoop = false; 
        this.barrier.awaitAdvance(0); 
        this.isFinished=true; 
       } 
       //System.out.println("i = "+i+" Size is: "+size+"\r"); 
       i++; 
      } 
     } catch (Exception e1) { 
      e1.printStackTrace(); 
     } 
    } 

    public boolean getIsFinished(){ 
     return this.isFinished; 
    } 
} 

class Reader implements Callable { 
    private Phaser barrier; 
    private ExecutorService executorService = Executors.newFixedThreadPool(1); 

    public Reader(Phaser phase) { 
     phase.register(); 
     this.barrier = phase; 
    } 

    @Override 
    public Object call() throws Exception { 
     System.out.println("Reading..."); 
     Thread.sleep(2000); 
     executorService.submit(new Writer(this.barrier)); 
     this.barrier.arrive(); 
     return 1000; 
    } 
} 

class Writer implements Callable { 
    private Phaser barrier; 

    public Writer(Phaser phase) { 
     phase.register(); 
     this.barrier = phase; 
    } 

    @Override 
    public Void call() throws Exception { 
     Thread.sleep(4000); 
     System.out.println("Wrote"); 
     this.barrier.arrive(); 
     return null; 
    } 
} 
+0

Fonctionne parfaitement. Merci pour votre suggestion! – Dan

+0

Juste découvert l'objet 'Phaser'. Merci encore. – Dan

0

D'après ce que je peux voir, vous n'attendez pas que le Writer finisse dans le Reader. Est-ce le problème que vous voyez?

Vous accédez également à isFinished à partir de plusieurs threads sans synchronisation (ce qui peut simplement retarder la fin de la boucle dans cette situation).

Je ne vois pas CyclicBarrier faire quelque chose.

Je ne suis pas sûr de ce que vous essayez de faire, mais je penserais à la façon dont je peux le faire plus simple. Par exemple, Reader et Writer peuvent-ils être combinés en une seule tâche? Alors, en attendant qu'ils finissent simplement serait:

executorService.invokeAll(tasks); 
System.out.println("Print metrics"); 

tasks est une collection de tâches (voir aussi this javadoc)

+0

Merci pour le commentaire et les recommandations. Malheur. les auteurs doivent être issus d'un lecteur et le lecteur ne peut pas bloquer et attendre. L'écrivain et le lecteur doivent fonctionner en parallèle dans certaines situations. Le CyclicBarrier fonctionne lorsque l'enregistreur est supprimé. L'écrivain, cependant, est une exigence nécessaire. (Pour tester le code CB, vous pouvez commenter le service d'exécution traitant de l'enregistreur et voir que cela fonctionne. 'Future f = executorService.submit (new Writer());') – Dan