简体   繁体   English

java 中的“简单”线程池

[英]a “simple” thread pool in java

I'm looking for a simple object that will hold my work threads and I need it to not limit the number of threads, and not keep them alive longer than needed.我正在寻找一个简单的 object 来保存我的工作线程,我需要它来不限制线程的数量,并且不会让它们保持比需要的时间更长的时间。 But I do need it to have a method similar to an ExecutorService.shutdown();但我确实需要它有一个类似于ExecutorService.shutdown();的方法。 (Waiting for all the active threads to finish but not accepting any new ones) (等待所有活动线程完成但不接受任何新线程)

so maybe a threadpool isn't what I need, so I would love a push in the right direction.所以也许线程池不是我需要的,所以我希望朝着正确的方向前进。 (as they are meant to keep the threads alive) (因为它们旨在使线程保持活力)

Further clarification of intent:进一步澄清意图:

each thread is an upload of a file, and I have another process that modifies files, but it waits for the file to not have any uploads.每个线程都是一个文件的上传,我有另一个修改文件的进程,但它等待文件没有任何上传。 by joining each of the threads.通过加入每个线程。 So when they are kept alive it locks that process.因此,当它们保持活动状态时,它会锁定该过程。 (each thread adds himself to a list for a specific file on creation, so I only join() threads that upload a specific file) (每个线程在创建时将自己添加到特定文件的列表中,所以我只加入()上传特定文件的线程)

One way to do what you awant is to use a Callable with a Future that returns the File object of a completed upload.做你想做的事情的一种方法是使用带有FutureCallable ,它返回已完成上传的File object。 Then pass the Future into another Callable that checks Future.isDone() and spins until it returns true and then do whatever you need to do to the file.然后将Future传递给另一个检查Future.isDone()并旋转直到它返回trueCallable ,然后对文件执行您需要执行的任何操作。 Your use case is not unique and fits very neatly into the java.util.concurrent package capabilities .您的用例不是唯一的,并且非常适合java.util.concurrent package 功能

One interesting class is ExecutorCompletionService class which does exactly what you want with waiting for results then proceeding with an additional calculation.一个有趣的 class 是ExecutorCompletionService class ,它完全符合您的要求,等待结果然后继续进行额外的计算。

A CompletionService that uses a supplied Executor to execute tasks.使用提供的 Executor 执行任务的 CompletionService。 This class arranges that submitted tasks are, upon completion, placed on a queue accessible using take.此 class 安排提交的任务在完成后放置在使用 take 可访问的队列中。 The class is lightweight enough to be suitable for transient use when processing groups of tasks. class 足够轻巧,适合在处理任务组时临时使用。

Usage Examples : Suppose you have a set of solvers for a certain problem, each returning a value of some type Result, and would like to run them concurrently, processing the results of each of them that return a non-null value, in some method use(Result r).用法示例:假设您有一组求解某个问题的求解器,每个求解器返回某种类型的 Result,并希望同时运行它们,以某种方法处理每个返回非空值的结果使用(结果 r)。 You could write this as:你可以这样写:

   void solve(Executor e, Collection<Callable<Result>> solvers)
              throws InterruptedException, ExecutionException 
   {
       CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
       for (Callable<Result> s : solvers) { ecs.submit(s); }
       int n = solvers.size();
       for (int i = 0; i < n; ++i) 
       {
           Result r = ecs.take().get();
           if (r != null) { use(r); }
       }
   }

You don't want an unbounded ExecutorService你不想要一个无界的 ExecutorService

You almost never want to allow unbounded thread pools, as they actually can limit the performance of your application if the number of threads gets out of hand.您几乎从不想允许无限线程池,因为如果线程数量失控,它们实际上会限制应用程序的性能。

You domain is limited by disk or network I/O or both, so a small thread pool would be sufficient.您的域受到磁盘或网络 I/O 或两者的限制,因此一个小的线程池就足够了。 You are not going to want to try and read from hundreds or thousands of incoming connections with a thread per connection.您不会想尝试从数百或数千个传入连接中读取每个连接一个线程。

Part of your solution, if you are receiving more than a handful of concurrent uploads is to investigate the java.niopackage and read about non-blocking I/O as well.如果您收到多个并发上传,您的解决方案的一部分是调查java.niopackage并阅读有关非阻塞 I/O 的信息。

Is there a reason that you don't want to reuse threads?您是否有不想重用线程的原因? Seems to me that the simplest thing would be to use ExecutorService anyway and let it reuse threads.在我看来,最简单的事情就是使用 ExecutorService 并让它重用线程。

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

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