java - 一个线程如何等到另一个线程完成才能触发某些操作

标签 java multithreading

如下代码所示,我在工作线程 fileThread 上加载了一个大文件,当该线程加载文件时,我创建了另一个线程 fileLoadIndicator 来在屏幕上显示类似忙碌指示符的内容。我现在要做的是:在 fileLoadIndicator 线程完成后,我想启用一个按钮,但只能在 fileLoadIndicator 线程完成后。

我的尝试:

loadFile();// the very heavy file
            /**
             * The below thread "fileLoadIndicator"is to show busy indicator while our main file  
 that takes approx. 8 seconds to be loaded
             * 
             */
            fileLoadIndicator = new Thread(fileLoadIndicatorRun);
            fileLoadIndicator.start();

            indicatorMonitor = new Thread(indicatorMonitorRun);
            indicatorMonitor.start();
 ...
 ...
 Runnable fileLoadIndicatorRun = new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        statusarea.append(Log.w(TAG, "busyIndicatorRunnable", "Loading."));
        StringBuilder sb = new StringBuilder(".");
        do {
            try {
                fileThread.join(1500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            sb.append(".");
            statusarea.append(sb.toString());
        } while (fileThread.getState() != State.TERMINATED);
        //statusarea.append("/n");
    }
};

Runnable indicatorMonitorRun = new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            fileLoadIndicator.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        setViewEnableState(Bpause, true);
    }
};

但是 indicatorMonitorRun 中发生的事情是,indicatorMonitor 线程等待整个方法 loadFile(),它处理重文件行按行,整个过程可能需要 70 分钟,完成。我只想启用一个按钮,只有当 fileLoadIndicator 线程完成时,我不应该等到整个文件加载和处理很长时间。

请告诉我该怎么做。

最佳答案

我建议使用 ExecutorService 来管理您的线程池,如果您使用的是 Java 8,请利用 CompletableFuture,因为它简化了这些类型的任务,而不需要复杂的线程等待/通知和 java.util.concurrency 类型,例如:

package so.thread.wait;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class LongThreadWait {

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

    // thread pool for long running loaders
    final ExecutorService fileLoaders = Executors.newCachedThreadPool();

    // hook to be invoked when the file is done loading
    final CompletableFuture<Long> completionFuture = new CompletableFuture<>();
    completionFuture.thenAcceptAsync(LongThreadWait::completionConsumer);

    fileLoaders.submit(new FileLoader(completionFuture));

    Thread.sleep(TimeUnit.SECONDS.toMillis(3));
  }

  private static void completionConsumer(Long millis) {
    System.out.println("Completed on Thread [" + Thread.currentThread().getName() + "] in " + millis + " ms");
  }

  private static class FileLoader implements Runnable {
    private CompletableFuture<Long> completionFuture;

    public FileLoader(CompletableFuture<Long> completionFuture) {
      this.completionFuture = completionFuture;
    }

    @Override
    public void run() {
      long start = System.currentTimeMillis();
      // load file for a long time
      System.out.println("Loading file on Thread [" + Thread.currentThread().getName() + "]");

      try {
        Thread.sleep(TimeUnit.SECONDS.toMillis(2));
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      long end = System.currentTimeMillis();
      // invoke the completion future with the elapsed milliseconds
      completionFuture.complete(end - start);
    }
  }

}

CompletableFuture.thenAcceptAsync(..) 默认在 JVM 的默认“ForkJoin”线程池中运行提供的钩子(Hook),还有一个可选的第二个参数,您可以在其中提供自己的 ExecutorService 来定义完成钩子(Hook)是哪个线程执行于。

这种类型的设置简化了线程管理和复杂的等待语义。

您还应注意,CompletableFuture 具有全面流畅的 API,可简化线程结果的复杂链接。

关于java - 一个线程如何等到另一个线程完成才能触发某些操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27744163/

相关文章:

java - 将需要的变量发送到子类方法 - 作为方法属性或作为 protected 类属性

java - hibernate/JPA : How to do the query that return the attribute of the DAO?

swift - 多线程核心数据有时返回nil属性

Java volatile 关键字未按预期工作

java - GData 与 Oauth 与服务帐户

java - 如何以枚举值作为方法参数调用 Java Mule 组件?

java - 二元补码运算符 (~) 无法正常工作(或者我不知道如何使用它)

c++ - 硬件功能的包装器

C# 线程问题和最佳实践

c# - 线程和垃圾收集