【问题标题】:Join a two different ExecutorService加入两个不同的 ExecutorService
【发布时间】:2020-12-19 06:00:48
【问题描述】:

我想加入两个在 ExecutorService 中执行的线程。

public class CURD {

  public static ExecutorService executorService = Executors.newCachedThreadPool();
  
 @Autowired
 Logging logging;

  public void Update(List<? extends HBase> save, List<? extends HBase> delete) {
        Thread t = new Thread(() -> {
            System.out.println("Started Main Thread...");
            try {
                Thread.sleep(1500);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("End Main Thread...");
        },"Thread-1");

        logging.setPredecessor(t);
        executorService.submit(t);
    }
}

二等: 此类线程应等待第一个线程完成。 但它不会等待第一个线程完成。 我不确定这是否是正确的做法。

请有人告诉我如何加入在 ExecutorService 中执行的两个线程?

import static com.demo.executorService;

public class Logging {
   
   private Thread predecessor;
   public void  setPredecessor(Thread t) {
        this.predecessor = t;
    }

  private void loggingInfo() {
      Thread run = new Thread( () ->{
                try {
                    if (predecessor != null) {
                        System.out.println(Thread.currentThread().getName() + " Started");
                        predecessor.join();
                        System.out.println(Thread.currentThread().getName() + " Finished");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            addTask(run);
   }

   public void addTask(Runnable run) {
        System.out.println("Runnable Thread logAround.....");
        CompletableFuture.runAsync((run), executorService).exceptionally(ex -> {
            System.out.println("exception occurred " + ex);
            return null;
        });
    }
}

【问题讨论】:

    标签: java multithreading parallel-processing java.util.concurrent


    【解决方案1】:

    如果想在一组线程之间进行同步,可以使用 Java CyclicBarrier 类:

    允许一组线程全部等待的同步辅助 彼此到达共同的障碍点。 CyclicBarriers 很有用 在涉及固定大小的线程方的程序中,必须 偶尔互相等待。屏障被称为循环的,因为 等待线程释放后可以重复使用。

    为此,首先创建CyclicBarrier 对象,其对应的方数,即:

    private final CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_PARIES);
    

    正式地从 Java 文档中可以看出各方是:

    在触发屏障之前必须调用 {@link #await} 的线程数

    非正式地,parties 是必须调用循环屏障并等待的线程数,然后它们才能继续前进。

    之后,您需要将屏障实例对象引用传递给每个应该等待的线程,并相应地调用waitbarrier.await())。如下:

      public void Update(..., CyclicBarrier barrier) {
            Thread t = new Thread(() -> {
                System.out.println("Started Main Thread...");
                try {
                     Thread.sleep(1500);
                     barrier.await(); // <--- wait on the barrier
                } catch (InterruptedException | BrokenBarrierException e) {
                     e.printStackTrace();
                 }
                System.out.println("End Main Thread...");
            },"Thread-1");
            ...
        }
    

    对必须等待的其他线程重复此过程。确保参与方的数量(NUMBER_OF_PARIES)与应在循环屏障上等待的线程数相匹配,否则会发生死锁。

    现在您正在使用cyclic barrier,您可以清理代码的某些部分,例如,您可以删除与Logging 类的字段predecessor 相关的所有逻辑。

    如果你只是想让Thread 2等待Thread 1,那么你可以使用CountDownLatch来代替。

    一种同步辅助,允许一个或多个线程等待直到 在其他线程中执行的一组操作完成。一个 CountDownLatch 使用给定的计数进行初始化。等待方法 阻塞直到当前计数由于调用 countDown() 方法,之后释放所有等待的线程并 任何后续调用 await 都会立即返回。这是一个 单发现象——计数无法重置。如果你需要一个 重置计数的版本,请考虑使用 CyclicBarrier。

    首先创建只有1 计数的CountDownLatch 对象:

    private final CountDownLatch block_thread2 = new CountDownLatch(1);
    

    并将其传递给Thread 2,既然您希望该线程等待Thread 1,请调用block_thread2.await();

          Thread run = new Thread( () ->{
                       try {
                            ....
                            block_thread2.await(); // wait for Thread 2
                       } catch (InterruptedException e) {
                            // deal with it
                       }
         });
                ...
    

    Thread 1 中添加wait.countDown();

      public void Update(...) {
            Thread t = new Thread(() -> {
                       System.out.println("Started Main Thread...");
                       try {
                            Thread.sleep(1500);
                            wait.countDown();
                       } catch (InterruptedException e) {
                            // deal with it
                }
                System.out.println("End Main Thread...");
            },"Thread-1");
            ...
        }
    

    因此,以这种方式,Thread 2 将等待Thread 1,但Thread 1 永远不会等待Thread 2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 2012-05-29
      • 2015-04-03
      • 1970-01-01
      • 2017-11-02
      相关资源
      最近更新 更多