线程互相等待

时间:2017-02-22 12:20:47

标签: java multithreading

我正在努力让我的线程像一场比赛一样互相追随,并希望线程相互等待。 像:

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();
    }
}

5 个答案:

答案 0 :(得分:2)

首先,拥有Random的多个实例非常糟糕,特别是如果它们是在彼此的毫秒内创建的(因为它们是以计算机的随机状态播种的,这在这些时间尺度上没有太大变化)

要使线程彼此等待,请使用CyclicBarrierjavadoc是一个很好的例子。但是,我不认为这是你所追求的,因为这会干扰比赛本身。

你可能想要的是一些裁判线程,这些裁判线程定期打印其他线程到目前为止运行的圈数。

答案 1 :(得分:1)

我认为规则是:

  • 所有线程必须在同一圈
  • 线程可以任何顺序完成他们的圈数,但在所有线程完成该圈之前无法进入下一圈。

上述规则要求线程之间采用某种形式的同步,Java中有一些同步选项

最初的提议是使用所有线程都可以访问的值,以便他们可以传达他们的进度并知道他们是否可以进入下一圈,并跟踪彼此的进度。

您的实施的一些一般性说明

  • System.out.println不保证在多线程应用程序中将消息打印到控制台的顺序。它们可以以不同的顺序到达控制台,而不是在代码中调用该方法。
  • Thread.sleep不保证确切的睡眠时间。

答案 2 :(得分:0)

您可以使用join

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

Join将阻止当前线程(我假设你的主线程)。当for循环结束时,所有线程都将完成他们的工作。

在你的情况下,你可以让每个线程做一圈而不是10圈。

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

答案 3 :(得分: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) {
    }
}

}

答案 4 :(得分: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 );
   }
}

执行日志:

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