我是一个 Tapestry-hibernate 用户,我遇到了一个问题:一旦超过 Executors.newFixedThreadPool(1);,我的 session 就会保持关闭状态;
我有以下代码,它将完美地适用于第一个线程,而其余线程则经历关闭的 session 。如果我将线程池增加到 10,所有线程都将正常运行。一旦超过固定线程池,我就会收到 session 关闭异常。我不知道如何打开它,因为它是由 Tapestry-Hibernate 管理的。如果我使用 newCachedThreadPool,一切都会完美运行。有人知道这里会发生什么吗?
public void setupRender() {
ExecutorService executorService = Executors.newFixedThreadPool(1);
final ConcurrentHashMap<String, Computer> map = new ConcurrentHashMap<>();
final String key = "myKey";
final Date date = new Date();
List<Future> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
final int thread = i;
Future future = executorService.submit(new Callable() {
@Override
public String call() {
try {
Computer computer = new Computer("Test Computer thread");
computer = getComputer(map, key, key, computer);
Monitor monitor = new Monitor();
monitor.setComputer(computer);
session.save(monitor);
session.flush();
System.out.println("thread " + thread);
try {
sessionManager.commit();
} catch (HibernateException ex) {
sessionManager.abort();
} finally {
session.close();
}
} catch (Exception ex) {
System.out.println("ex " + ex);
}
System.out.println( new Date().getTime() - date.getTime());
return "completed";
}
});
futures.add(future);
}
for(Future future : futures) {
try {
System.out.println(future.get());
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(MultiThreadDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public synchronized Computer getComputer(ConcurrentHashMap<String, Computer> map, String key, String thread, Computer computer) {
if (map.putIfAbsent(key, computer) == null) {
session.save(computer);
} else {
computer = map.get(key);
}
return computer;
}
最佳答案
我之前已经告诉过你了......你必须使用ParallelExecutor
或调用PerThreadManager.cleanup()
。您需要了解 Tapestry-hibernate 有 PerThread如果您在正常请求/响应(或 ParallelExecutor)之外使用它们,则必须清理这些范围内的服务。
我也不认为您应该调用session.close()
。你应该模仿CommitAfterWorker .
它可能看起来像:
@Inject PerThreadManager perThreadManager;
@Inject HibernateSessionManager sessionManager; // this is a proxy to a per-thread value
@Inject Session session; // this is a proxy to a per-thread value
public void someMethod() {
ExecutorService executorService = ...;
executorService.submit(new Callable() {
public String call() {
try {
Monitor monitor = ...
session.save(monitor);
session.flush(); // optional
sessionManager.commit();
} catch (Exception ex) {
sessionManager.abort();
} finally {
// this allows Session and HibernateSessionManager to
// clean up after themselves
perThreadManager.cleanup();
}
return ...
}
});
}
如果您选择使用ParallelExecutor (和 Invokable )而不是 Executors.newFixedThreadPool(1)
您可以删除对 PerThreadManager
的引用,因为它会自动清理线程。
关于java - Tapestry Hibernate session 超出 ExecutorService 固定线程池后关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19988480/