繁体   English   中英

一个线程如何等待,直到另一个线程完成触发某些操作

[英]How one thread can wait until another one finishes to fire some actions

如下面的代码所示,我在工作线程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”线程池中运行提供的钩子,有一个可选的第二个参数,您可以在其中提供自己的ExecutorService来定义执行完成钩子的线程。

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

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

考虑使用CountDownLatch 将其初始化为1.加载线程完成后,可以调用countDown 您的监视器线程可以轮询计数或只是等待完成。

您可以使用“ExecutorService”来创建线程池,然后监视线程并等待线程终止以启用该按钮。

 class FileThreadThread implements Runnable {
        public FileThreadThread() {

        }

        @Override
        public void run() {

        }       
}


class FileLoadIndicatorRunThread implements Runnable {
    private ExecutorService fileLoadIndicatorExecutor = null;

    @Override
    public void run() {
        if (fileLoadIndicatorExecutor == null || fileLoadIndicatorExecutor.isShutdown()) {
            fileLoadIndicatorExecutor = Executors.newCachedThreadPool(CustomizableThreadFactory.createSingleNamedFactory("FileLoaderThreadPool"));
        }


        for(int i=0; number_of_files; i++){
            fileLoadIndicatorExecutor.execute(new FileThreadThread());
        }
        //Request executor shutdown after all threads are completed
        fileLoadIndicatorExecutor.shutdown();           

        while (isRunning) {
            boolean threadTerminated = fileLoadIndicatorExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
            if(threadTerminated){
                // enable a button

            isRunning =  false;
            }               
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM