在java中使用多线程运行方法

在java中使用多线程运行方法,java,multithreading,threadpool,httpresponse,runnable,Java,Multithreading,Threadpool,Httpresponse,Runnable,我的方法是 public List<SenderResponse> sendAllFiles(String folderName) { List<File> allFiles = getListOfFiles(); List<SenderResponse> finalResponse = new ArrayList<SenderResponse>(); for (File file : allFiles) {

我的方法是

public List<SenderResponse> sendAllFiles(String folderName) {
    List<File> allFiles = getListOfFiles();
    List<SenderResponse> finalResponse = new ArrayList<SenderResponse>();
    for (File file : allFiles) {
        finalResponse.getResults().add(sendSingleFile(file));
    }
    return finalResponse;
}
public List sendAllFiles(字符串folderName){
List allFiles=getListOfFiles();
List finalResponse=new ArrayList();
用于(文件:所有文件){
finalResponse.getResults().add(sendSingleFile(file));
}
返回最终响应;
}
它作为单个线程运行。我想使用
多线程运行
sendSingleFile(file)
,这样可以减少发送文件的总时间

如何使用
multi-thread
s为各种文件运行
sendSingleFile(file)
,并获得最终响应

我发现很少有文章使用
threadpoolexecutor
。但是如何处理在
sendSingleFile(file)
过程中得到的响应,并将其添加到最后一个
SenderResponse


我对多线程有点陌生。请建议处理这些文件的最佳方法

您可以从编写适用于单线程解决方案的代码开始。你发布的代码甚至不会编译;正如方法签名所说,返回
SenderResponse
;而您在方法中使用/返回一个
列表

当这些东西起作用时,您可以继续执行以下操作:

  • 您可以创建 ,基于您想要的线程数
  • 您向该服务提交任务
  • 每个任务都知道该结果列表对象。任务完成其工作,并将结果添加到该结果列表中

需要注意的一点是:确保
add()
以某种方式同步-让多个线程更新普通ArrayList是不安全的。

定义一个executor服务

ExecutorService executor = Executors.newFixedThreadPool(MAX_THREAD); //Define integer value of MAX_THREAD
然后,对于每项工作,您可以执行以下操作:-

Callable<SenderResponse> task = () -> {
    try {
        return sendSingleFile(file);
    }
    catch (InterruptedException e) {
        throw new IllegalStateException("Interrupted", e);
    }
};

Future<SenderResponse> future = executor.submit(task);

future.get(MAX_TIME_TO_WAIT, TimeUnit.SECONDS);  //Blocking call. MAX_TIME_TO_WAIT is max time future will wait for the process to execute.
可调用任务=()->{
试一试{
返回sendSingleFile(文件);
}
捕捉(中断异常e){
抛出新的非法状态异常(“中断”,e);
}
};
未来=执行者提交(任务);
获取(最大等待时间,时间单位为秒)//阻塞呼叫。MAX_TIME_TO_WAIT是future将等待进程执行的最长时间。

对于您的情况,我会使用工作窃取池(ForkJoin executor service)并向其提交“作业”。如果您使用的是番石榴,您可以将其包装在一个
listingdecorator
中,这将允许您在它返回的未来添加一个侦听器

例如:

// create the executor service
ListeningExecutorService exec = MoreExecutors.listeningDecorator(Executors.newWorkStealingPool());

for(Foo foo : bar) {
    // submit can accept Runnable or Callable<T>
    final ListenableFuture<T> future = exec.submit(() -> doSomethingWith(foo));
    // Run something when it is complete.
    future.addListener(() -> doSomeStuff(future), exec);
}
//创建执行器服务
ListingExecutorService exec=MoreExecutors.ListingDecorator(Executors.newWorkStealingPool());
for(Foo-Foo:bar){
//submit可以接受Runnable或Callable
final ListenableFuture=exec.submit(()->doSomethingWith(foo));
//完成后运行某个程序。
addListener(()->doSomeStuff(future),exec);
}

请注意,无论未来是否成功,都将调用侦听器。

您可以使用并行流
finalResponse=allFiles.stream().parallel().map(this::sendSinfleFile.collect()。我不确定
getResults()
做了什么。@eckes我认为对getResults()的调用只是表明OP给出的代码根本不起作用的一个迹象。您的顺序代码甚至无法编译。先把它修好。然后阅读关于executors()的教程,以及相关的javadoc。然后试试看。缺少“收集”部分,即将所有不同的响应捆绑到一个列表中。是的,你说得对。但我只打算将此代码用于一项工作。所以,OP必须把它放在一个提交作业的循环中,然后他可以在未来的列表中做一个循环来获得响应。例如,是的。无论什么你的答案可能和我的一样好;更具体一点;我的投票结果也是如此。我曾经开始编写适用于单线程解决方案的代码(实际上是在一周前),然后我不得不完全重写它以用于多线程。这不是一个问题。只是一个评论。对不起,我看错了。关键是:OP甚至没有单线程解决方案的正确代码。除此之外;这是关于经验的:当你知道你在做什么时,你可以放下一个单线程的解决方案,它在为多线程增强时不会给你带来太多麻烦。