触发多个线程以获取数据时,查询无法获取结果



我有一个 Spring 引导应用程序,我使用 java 并发包的可调用对象在 postgres 表上触发 5 个数据库查询。

我正在使用的表"用户"非常小,只有 6 个条目,但应用程序仍然需要 40 多秒来显示数据,并在 40 秒后出现异常。

DataServiceImpl.java

@Service
public class DataServiceImpl {
/*@Autowired
private EntityManagerFactory emf;*/
@Autowired
private EntityManager entityManager;
public List<Object> showUser(int firstParam, int secondParam) {
//EntityManager entityManager = emf.createEntityManager();
String sql = "select * from sunny.user where id between ?1 and ?2";
Query query = entityManager.createNativeQuery(sql);
query.setParameter(1, firstParam);
query.setParameter(2, secondParam);
return query.getResultList();
}
}

用户服务.java

@Service
public class UserService {
@Autowired
private DataServiceImpl dataServiceImpl;
public List<Object> callUser() throws InterruptedException, ExecutionException {
int startParam = 1;
int endParam = 6;
List<Future<List<Object>>> futures = new ArrayList<>();
ExecutorService executorService = Executors.newCachedThreadPool();
List<Object> b = null;
for (int i = startParam; i < 6; i++) {
if (i == 1)
endParam = startParam + 1;
else {
startParam += 1;
endParam += 1;
}
Callable<List<Object>> callable = new ProcessingData(startParam, endParam);
futures.add(executorService.submit(callable));
}
executorService.awaitTermination(40, TimeUnit.SECONDS);
int i = 0;
for (Future<List<Object>> f : futures) {
if (i == 0) {
b = new ArrayList<>(f.get());
} else {
b.add(f.get());
}
i++;
}
return b;
}
private class ProcessingData implements Callable<List<Object>> {
private int firstParam;
private int secondParam;
/*
* @Autowired private DataServiceImpl dataServiceImpl;
*/
public ProcessingData(int firstParam, int secondParam) {
super();
this.firstParam = firstParam;
this.secondParam = secondParam;
}
@Override
public List<Object> call() throws Exception {
return dataServiceImpl.showUser(firstParam, secondParam);
}
}
}

你可以在这里找到完整的代码 - Git 代码在这里

谁能告诉我我哪里做错了? 40秒后异常:-

1  Iftekhar
2  Sunny
2018-05-27 13:29:19.096 ERROR 9836 --- [nio-8085-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: java.util.ArrayList cannot be cast to [Ljava.lang.Object;] with root cause
java.lang.ClassCastException: java.util.ArrayList cannot be cast to [Ljava.lang.Object;
at com.example.controller.UserController.showUser(UserController.java:24) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) ~[spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.31.jar:8.5.31]

如您所见,我只获取前 2 行的数据,之后出现异常,因为其他查询无法在 40 秒内完成,它们会抛出异常,因为它们返回的值为 null。

触发的查询:-

Hibernate: select * from sunny.user where id between ? and ?
Hibernate: select * from sunny.user where id between ? and ?
Hibernate: select * from sunny.user where id between ? and ?
Hibernate: select * from sunny.user where id between ? and ?
Hibernate: select * from sunny.user where id between ? and ?
executorService.awaitTermination(40, TimeUnit.SECONDS);

这将阻止 40 秒,但为了使其正常工作,您必须先调用executorService.shutdown();。所以试试看

executorService.shutdown();
executorService.awaitTermination(40, TimeUnit.SECONDS);

此外,awaitTermination返回boolean,指示是否命中超时(true=任务正常完成,false=超时(或在指定时间段之前完成的任务 - 您似乎忽略了该值,而我会以不同的方式处理这两种情况。

最新更新