我正在尝试提高弹簧应用程序的性能,调用大约8-10个查询,并且它将需要大约15到120秒,具体取决于它查询的数据量,我提出了CompletableFuture /在Java 8中实现它的未来方式。但是,我一直停留在主线程不等待异步线程完成的位置。以下是我到目前为止实施的代码。
我打算使用未来'回去实施它。和ThreadPoolExecutor并有一个线程,等待threadPoolExecutor中生成的可调用线程的完成返回数据。
问题:在java中实现CompletableFuture的任何简单方法,主线程在将数据返回给客户端之前等待线程池中的所有线程完成?
InvokeCallable .java
package net.sampleSpring.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
@Component
public class InvokeCallable {
@Autowired
private ApplicationContext context;
// @Autowired
// @Qualifier("threadPoolExecutor")
// private ThreadPoolTaskExecutor executorThreadPool;
public void invokeCallables() throws InterruptedException, ExecutionException {
List<CompletableFuture<Integer>> lst = new ArrayList<>();
CallableOne callableOne = context.getBean(CallableOne.class);
CallableTwo callableTwo = context.getBean(CallableTwo.class);
CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
@Override
public Integer get() {
try {
return callableOne.call();
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}
}
);
CompletableFuture<String> completableFuture2 = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {
return callableTwo.call();
} catch (Exception e) {
e.printStackTrace();
}
return "1";
}
}
);
CompletableFuture.allOf(completableFuture1, completableFuture2).thenApply(
i -> {
System.out.println("Completed running the futures");
System.out.println("future 1" + completableFuture1.join().toString());
System.out.println("future 2" + completableFuture2.join().toLowerCase());
return i;
}
);
}
}
CallableTwo.java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.concurrent.Callable;
@Component
@Scope("prototype")
public class CallableTwo {
public String call() throws Exception {
Thread.sleep(2000);
return "1000";
}
}
CallableOne.java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class CallableOne {
public Integer call() throws Exception {
Thread.sleep(2000);
return 1;
}
}
sampleSpringResource.java 使用restful服务调用InvokeCallable.java的代码
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.util.concurrent.ExecutionException;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.json.XMLTokener.entity;
/* ItemValue Web service
*
*/
@Path("/")
@Service
public class sampleSpringResource {
@Inject
private InvokeCallable callable;
private static final Logger LOG = LogManager.getLogger();
@GET
@Path("/changeme/")
@Produces(APPLICATION_JSON)
public Response getsampleSpring() throws ExecutionException, InterruptedException {
callable.invokeCallables();
}
}
答案 0 :(得分:0)
感谢Abhijit指向正确的位置。我已经按照以下方式实现了它。
<强> SampleSpringResourc.java 强>
/* ItemValue Web service
*
*/
@Path("/")
@Service
public class sampleSpringResource {
@Inject
private InvokeCallable callable;
private static final Logger LOG = LogManager.getLogger();
@GET
@Path("/changeme/")
@Produces(APPLICATION_JSON)
public Response getsampleSpring() throws ExecutionException, InterruptedException {
System.out.print("In getSampleSpring()..");
try {
callable.invokeCallables();
System.out.println("returning from the result");
return LOG.exit(Response.status(Response.Status.OK).entity("Success").build());
} catch (DataAccessException ex) {
return LOG.exit(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ServiceError(ErrorCode.INTERNAL_SERVER_ERROR, ex.getMessage())).build());
} catch (Exception ex) {
return LOG.exit(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ServiceError(ErrorCode.INTERNAL_SERVER_ERROR, ex.getMessage())).build());
}
}
}
<强> InvokeCallable 强>
@Component
public class InvokeCallable {
@Autowired
private ApplicationContext context;
@Autowired
private CallableTwo callableTwo;
@Autowired
private CallableOne callableOne;
public void invokeCallables() throws Exception {
List<CompletableFuture<Integer>> lst = new ArrayList<>();
System.out.println("Callable one start " + new Date());
CompletableFuture<Integer> completableFuture1 = callableOne.call();
System.out.println("Callable one end " + new Date());
System.out.println("Callable two start " + new Date());
CompletableFuture<String> completableFuture2 = callableTwo.call();
System.out.println("Callable two end " + new Date());
CompletableFuture.allOf(completableFuture1, completableFuture2).join();
System.out.println("Completable future all end " + new Date());
}
}
<强> CallableTwo 强>
@Component
@Scope("prototype")
public class CallableTwo {
@Async
public CompletableFuture<String> call() throws Exception {
Thread.sleep(2000);
return CompletableFuture.completedFuture("1000");
}
}
<强> CallableOne 强>
@Component
@Scope("prototype")
public class CallableOne {
@Async
public CompletableFuture<Integer> call() throws Exception {
Thread.sleep(2000);
return CompletableFuture.completedFuture(1);
}
}
下面的日志显示了两个线程的合并时间结果。每个线程大约需要2秒钟。
<强>日志强>
2017-08-23 11:27:30,118 INFO [stdout] (default task-4) In getSampleSpring()..Callable one start Wed Aug 23 11:27:30 CDT 2017
2017-08-23 11:27:30,124 INFO [stdout] (default task-4) Callable one end Wed Aug 23 11:27:30 CDT 2017
2017-08-23 11:27:30,125 INFO [stdout] (default task-4) Callable two start Wed Aug 23 11:27:30 CDT 2017
2017-08-23 11:27:30,126 INFO [stdout] (default task-4) Callable two end Wed Aug 23 11:27:30 CDT 2017
2017-08-23 11:27:32,138 INFO [stdout] (default task-4) Completable future all end Wed Aug 23 11:27:32 CDT 2017
2017-08-23 11:27:32,138 INFO [stdout] (default task-4) returning from the result