2017-02-22 17 views
1

Я стараюсь, чтобы мои темы следовали друг за другом, как гонка, и хотите, чтобы потоки подождали друг друга. как:Темы, ожидающие друг друга

DUCK is on his 1 lap 
PIGGY is on his 1 lap 
ELEFANT is on his 1 lap 
STAR is on his 1 lap 

DUCK is on his 2 lap 
PIGGY is on his 2 lap 
ELEFANT is on his 2 lap 
STAR is on his 2 lap 

и так далее ..

public class ExThread implements Runnable { 

    String name; 
    Random r = new Random(); 
    int count; 
    int sleepTimer; 

    public ExThread(String name) { 
     this.name = name; 
    } 

    @Override 
    public void run() { 
     try { 
      for(int i = 0; i < 10; i++) { 
       count++; 
       sleepTimer = r.nextInt(1000)+1; 
       Thread.sleep(sleepTimer); 
       System.out.println(
        name + " Starts after "+sleepTimer+" milliseconds break"); 
       System.out.println(
        name+" is on his "+count+" lap"); 

      } 
      System.out.println(name+" completes the race!!!"); 
     } 
     catch (Exception e){} 
    } 

public class ThreadsEx { 

    public static void main(String[] args) throws InterruptedException { 
     Thread t1 = new Thread(new ExThread("STAR")); 
     Thread t2 = new Thread(new ExThread("ELEFANT")); 
     Thread t3 = new Thread(new ExThread("PIGGY")); 
     Thread t4 = new Thread(new ExThread("DUCK")); 
     t1.start(); 
     t2.start(); 
     t3.start(); 
     t4.start(); 
    } 
} 
+2

Можете ли вы быть немного более конкретными. В чем дело? Каковы ваши текущие результаты? Каким образом потоки «следуют и ждут» друг друга? – GregaMohorko

+0

@CasperFlintrup вы имеете в виду одно нитьное осложнение, начнется другой поток? Я не ошибаюсь ? –

+0

Взгляните на [Phaser] (https://dzone.com/articles/java-7-understanding-phaser). Это должно помочь вам. Я пытаюсь написать пример чуть позже – rvit34

ответ

0

Вы можете использовать join.

for(i = 0; i < threads.length; i++){ 
    threads[i].join(); 
} 

Присоединиться будет блокировать текущую резьбу (основная тема в вашем случае, я полагаю). Когда цикл for заканчивается, все потоки будут выполняться с их работой.

В вашем случае, вы могли бы сделать каждый поток сделать один круг вместо 10.

for(j = 0; j < numberOfLaps; j++){ 
    for(i = 0; i < threads.length; i++){ 
     threads[i].join(); 
    } 
} 
0

Вы можете использовать https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CyclicBarrier.html для этого.

Кодекс идет как этот

import java.util.Random; 
import java.util.concurrent.CyclicBarrier; 

public class ExThread implements Runnable { 

String name; 
Random r = new Random(); 
int count; 
int sleepTimer; 
CyclicBarrier barrier; 

public ExThread(String name, CyclicBarrier barrier) { 
    this.name = name; 
    this.barrier = barrier; 
} 

public static void main(String[] args) throws InterruptedException { 
    CyclicBarrier barrier = new CyclicBarrier(4); 

    Thread t1 = new Thread(new ExThread("STAR", barrier)); 
    Thread t2 = new Thread(new ExThread("ELEFANT", barrier)); 
    Thread t3 = new Thread(new ExThread("PIGGY", barrier)); 
    Thread t4 = new Thread(new ExThread("DUCK", barrier)); 
    t1.start(); 
    t2.start(); 
    t3.start(); 
    t4.start(); 
} 

@Override 
public void run() { 
    try { 
     for (int i = 0; i < 10; i++) { 
      count++; 
      sleepTimer = r.nextInt(1000) + 1; 
      Thread.sleep(sleepTimer); 
      System.out.println(
        name + " Starts after " + sleepTimer + " milliseconds break"); 
      System.out.println(
        name + " is on his " + count + " lap"); 
      barrier.await(); 
     } 

     System.out.println(name + " completes the race!!!"); 
    } catch (Exception e) { 
    } 
} 

}

2

Во-первых, это очень плохо иметь несколько экземпляров Random особенно, если они созданы в миллисекундах друг друга (потому что они высевают со случайным состоянием ваш компьютер, который не сильно меняется по сравнению с этими временными шкалами)

Чтобы потоки ожидают друг друга, используйте CyclicBarrier. javadoc - отличный пример. Однако я не думаю, что это то, что вам нужно, так как это будет мешать самой гонке.

Что бы вы могли захотеть, это какая-то рефериная нить, которая периодически печатает кружки, которые другие потоки бежали до сих пор.

1

Я предполагаю, что правила:

  • Все нити должны быть на том же круге
  • Нити могут закончить их круг в любом порядке, но не может прогрессировать в следующий круг, прежде чем все нити закончили этот круг.

Эти правила выше, требуют некоторой формы синхронизации между потоками и есть несколько вариантов синхронизации доступны в Java

Первоначальная предложение было бы использовать значение, которое все потоки имеют acces чтобы они могли сообщить о своем прогрессе и узнать, могут ли они продвинуться на следующий круг или нет и следить за прогрессом друг друга.

Некоторые общие примечания к вашей реализации

  • System.out.println не гарантирует порядок печати сообщений на консоль в многопоточных приложениях. Они могут поступать в консоль другого порядка, чем этот метод вызывается в коде.
  • Thread.sleep не гарантирует точное время сна.
0

Вы должны использовать java.util.concurrent, как это:

import java.util.Random; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.CyclicBarrier; 

public class RendezVous extends Thread { 

    private final CountDownLatch _start; 
    private final CyclicBarrier _rdv; 
    private final CountDownLatch _stop; 

    public RendezVous(
     String   name, 
     CountDownLatch start, 
     CyclicBarrier rdv, 
     CountDownLatch stop ) 
    { 
     super(name); 
     _start = start; 
     _rdv = rdv; 
     _stop = stop; 
     start(); 
    } 

    @Override 
    public void run() { 
     final Random rnd = new Random(System.currentTimeMillis()); 
     try { 
     System.out.println(getName() + " is started"); 
     _start.countDown(); 
     System.out.println(getName() + " waits for others"); 
     _start.await(); 
     System.out.println(getName() + " is running"); 
     for(int count = 0, i = 0; i < 10; ++i, ++count) { 
      final long sleepTimer = rnd.nextInt(1000) + 1; 
      sleep(sleepTimer); 
      System.out.println(getName() +" is on his " + count + " lap"); 
      _rdv.await(); 
     } 
     _stop.countDown(); 
     _stop.await(); 
     System.out.println(getName() + " completes the race"); 
     } 
     catch(final Exception e) { 
     e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     final CountDownLatch start = new CountDownLatch(4); 
     final CyclicBarrier rdv = new CyclicBarrier(4); 
     final CountDownLatch stop = new CountDownLatch(4); 
     new RendezVous("STAR" , start, rdv, stop); 
     new RendezVous("ELEFANT", start, rdv, stop); 
     new RendezVous("PIGGY" , start, rdv, stop); 
     new RendezVous("DUCK" , start, rdv, stop); 
    } 
} 

журнал Execution:

DUCK is started 
STAR is started 
DUCK waits for others 
PIGGY is started 
ELEFANT is started 
PIGGY waits for others 
STAR waits for others 
PIGGY is running 
STAR is running 
ELEFANT waits for others 
DUCK is running 
ELEFANT is running 
STAR is on his 0 lap 
PIGGY is on his 0 lap 
DUCK is on his 0 lap 
ELEFANT is on his 0 lap 
DUCK is on his 1 lap 
STAR is on his 1 lap 
ELEFANT is on his 1 lap 
PIGGY is on his 1 lap 
STAR is on his 2 lap 
ELEFANT is on his 2 lap 
PIGGY is on his 2 lap 
DUCK is on his 2 lap 
STAR is on his 3 lap 
PIGGY is on his 3 lap 
ELEFANT is on his 3 lap 
DUCK is on his 3 lap 
DUCK is on his 4 lap 
PIGGY is on his 4 lap 
ELEFANT is on his 4 lap 
STAR is on his 4 lap 
STAR is on his 5 lap 
PIGGY is on his 5 lap 
ELEFANT is on his 5 lap 
DUCK is on his 5 lap 
STAR is on his 6 lap 
DUCK is on his 6 lap 
PIGGY is on his 6 lap 
ELEFANT is on his 6 lap 
PIGGY is on his 7 lap 
ELEFANT is on his 7 lap 
STAR is on his 7 lap 
DUCK is on his 7 lap 
ELEFANT is on his 8 lap 
DUCK is on his 8 lap 
PIGGY is on his 8 lap 
STAR is on his 8 lap 
STAR is on his 9 lap 
ELEFANT is on his 9 lap 
DUCK is on his 9 lap 
PIGGY is on his 9 lap 
DUCK completes the race 
PIGGY completes the race 
ELEFANT completes the race 
STAR completes the race