Java chain lock a bit differently

时间:2018-11-13 07:51:04

标签: java multithreading

I have 1,2,3 threads each have A,B,C sections to run sequentially like 1A, 2A, 3A, 1B, 2B, 3B, 1C, 2C, 3C. So after 1A finishes its run it waits for the signal of thread 3 to continue with its section B and so on. How could I achieve this? I have to reuse the threads so I cannot make threads from sections.

4 个答案:

答案 0 :(得分:2)

这是CyclicBarrier的工作:

public class BarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3); // three threads

        new Thread(new Task(1, barrier)).start();
        new Thread(new Task(2, barrier)).start();
        new Thread(new Task(3, barrier)).start();
    }

    private static class Task implements Runnable {
        private final int number;
        private final CyclicBarrier barrier;

        public Task(int number, CyclicBarrier barrier) {
            this.number = number;
            this.barrier = barrier;
        }

        @Override
        public void run() {
            try {
                System.out.println(number + "A");
                barrier.await();
                System.out.println(number + "B");
                barrier.await();
                System.out.println(number + "C");
            }
            catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            catch(BrokenBarrierException e) {
                // too bad
            }
        }
    }
}

答案 1 :(得分:0)

如果1,2,3的顺序不重要,但是所有A,所有B,所有C的顺序都很重要,则, 使用2 CountDownLatch。 您可以直接开始A部分。完成某节后,请倒数CountDownLatch。

在B部分启动CountDownLatch的await()之前。

因此应该有2个CountDownLatch闩锁来同步B部分和C部分。

    public class Test extends Thread
{

  CountDownLatch cdlA;
  CountDownLatch cdlB;
  int threadId;

  public Test(CountDownLatch cdlA, CountDownLatch cdlB,int threadNumber)
  {
    this.cdlA = cdlA;
    this.cdlB = cdlB;
    threadId = threadNumber;
  }

  @Override
  public void run()
  {
    test();
  }

  private   void test()
  {
    try
    {
      System.out.println("section A" +threadId);
      cdlA.countDown();

      cdlA.await();

      System.out.println("section B" +threadId);
      cdlB.countDown();

      cdlB.await();

      System.out.println("section C" +threadId);
    }
    catch (InterruptedException e)
    {

    }

  }

  public static void main(String[] args) throws InterruptedException
  {
    CountDownLatch a = new CountDownLatch(3);
    CountDownLatch b = new CountDownLatch(3);

    final Test test1 = new Test(a, b,1);

    final Test test2 = new Test(a, b,2);

    final Test test3 = new Test(a, b,3);

    test1.start();
    test2.start();
    test3.start();
  }
}

答案 2 :(得分:0)

如果您有一个知道该做什么的委托,则可以使用执行程序服务来控制执行。例如。为每个线程创建一个执行程序服务,提交,然后使用Future.get等待执行完成。

否则就是用一种球。

static public void task(int no){
    System.out.println("task " + no + " on " + Thread.currentThread().getName());
}

public static void main(String[] args) throws Exception{
    BlockingQueue<Object> permissions = new ArrayBlockingQueue<>(1);

    var A = new Thread(){
        BlockingQueue<Object> waiting = new ArrayBlockingQueue<>(1);
        public void run(){
            for(int i = 0; i<3; i++){
                Object ball = null;
                try{
                    ball = waiting.take();
                    task(i);
                } catch(InterruptedException e){
                    throw new RuntimeException(e);
                }finally{
                    permissions.offer(ball);
                }
            }
        }
    };

    var B = new Thread(){
        BlockingQueue<Object> waiting = new ArrayBlockingQueue<>(1);
        public void run(){
            for(int i = 0; i<3; i++){
                Object ball = null;
                try{
                    ball = waiting.take();
                    task(i);
                } catch(InterruptedException e){
                    throw new RuntimeException(e);
                }finally{
                    permissions.offer(ball);
                }
            }
        }
    };

    A.start();
    B.start();
    Object ball = new Object();
    A.waiting.offer(ball);
    ball = permissions.take();
    B.waiting.offer(ball);
    ball = permissions.take();
    A.waiting.offer(ball);
    ball = permissions.take();
    B.waiting.offer(ball);
    ball = permissions.take();
    A.waiting.offer(ball);
    ball = permissions.take();
    B.waiting.offer(ball);
    ball = permissions.take();
    System.out.println("finished");

肯定有更好的方法,我认为您可以看到这是不可扩展的,您必须知道任务数。 Object球没有实际用途,而有一个新的Object();可以使用,甚至可以为空。

答案 3 :(得分:0)

这是我解决该问题的方法。我认为其背后的想法接近马特的解决方案。谢谢大家。

 @Test
void test() throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(3);
    SynchronousQueue<Integer> chromeQueue = new SynchronousQueue<>();
    SynchronousQueue<Integer> firefoxQueue = new SynchronousQueue<>();
    SynchronousQueue<Integer> ieQueue = new SynchronousQueue<>();

    Runnable ieRunnable = () -> {
        try {
            firefoxQueue.take();
            System.out.println("ieRunnable section 1");
            ieQueue.put(1);
            firefoxQueue.take();
            System.out.println("ieRunnable section 2");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    };

    Runnable firefoxRunnable = () -> {
        try {
            chromeQueue.take();
            System.out.println("firefoxRunnable section 1");
            firefoxQueue.put(1);
            chromeQueue.take();
            System.out.println("firefoxRunnable section 2");
            firefoxQueue.put(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    };

    Runnable chromeRunnable = () -> {
        try {
            ieQueue.take();//waits    
            System.out.println("chromeRunnable section 1");
            chromeQueue.put(1);//starts firefoxRunnable
            ieQueue.take();//wait for ieRunnable to signal
            System.out.println("chromeRunnable section 2");
            chromeQueue.put(1);//makes firefoxRunnable to continue
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    };
    executor.execute(chromeRunnable);
    executor.execute(firefoxRunnable);
    executor.execute(ieRunnable);
    ieQueue.put(1);
    executor.shutdown();
    try {
        if (!executor.awaitTermination(5, TimeUnit.MINUTES)) {
            executor.shutdownNow();
        }
    } catch (InterruptedException e) {
        executor.shutdownNow();
    }
}