我使用非常标准的Java ODBC功能 - 从池中获取Connection
,创建Statement
并执行它。
我们的用例是游戏,记录游戏进度 - ODBC调用主要是对存储过程的调用,并且在大多数情况下没有返回值。因此,ODBC调用阻塞的事实很烦人 - 游戏已基于回合,但如果数据库速度慢,用户可以看到更长的暂停。
如果我不需要检查ODBC调用的结果,是否有任何内置功能可以异步执行语句?如果没有,在没有编写大量代码的情况下,这样做的好方法是什么?如果发生ODBC异常,我仍然需要捕获它们。
这个问题虽然不相同但看起来很相似...... Is asynchronous jdbc call possible?
答案 0 :(得分:9)
我们假设你有OdbcCaller
:
public class OdbcCaller {
public void callODBC() {
// call ODBC directly
// ...
}
您可以将其包装在一个可运行的任务中,并将该任务提交给一个线程池,使其以异步方式执行:
public void asyncCallODBC() {
// wrap the call with a runnable task
executor.execute(new Runnable() {
@Override
public void run() {
callODBC();
}
});
// the above line would return immediately.
}
executor
是JDK提供的线程池实现,可以定义如下:
Executor executor = new ThreadPoolExecutor(/* core pool size */5,
/* maximum pool size */10,
/* keepAliveTime */1,
/* time unit of keepAliveTime */TimeUnit.MINUTES,
/* work queue */new ArrayBlockingQueue<Runnable>(10000),
/* custom thread factory */new ThreadFactory() {
private AtomicInteger counter = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "asyncCaller-" + (counter.incrementAndGet()));
return t;
}
},
/*
* policy applied when all tasks are occupied and task
* queue is full.
*/new ThreadPoolExecutor.CallerRunsPolicy());
ThreadPoolExecutor
具有高度可配置性,并在JavaDoc中记录,您可能需要先阅读它。
以下是根据我的经验对线程池配置的一些建议:
ThreadFactory
并为线程提供有意义的名称是一种很好的做法。当您需要检查线程状态(使用jstack
或其他工具)时,它将非常有用。答案 1 :(得分:0)
public class Snippet
{
static int i = 0;
public static void main(String[] args) throws SQLException
{
ExecutorService eventExecutor = Executors.newSingleThreadExecutor();
final Connection c = DriverManager.getConnection("jdbc:url", "user",
"password");
Runnable r = new Runnable()
{
public void run()
{
try
{
CallableStatement s = c
.prepareCall("{ call your_procedure(?) }");
s.setInt(1, i);
s.execute();
} catch (SQLException e)
{
e.printStackTrace();
}
}
};
for (; i < 100; i++)
eventExecutor.submit(r);
}
}
使用100个不同的参数对your_procedure进行100次调用。
答案 2 :(得分:0)
如果您使用的是EJB 3.1,则可以创建一个@Stateless
EJB,并标记其中一个方法@Asynchronous
。这是企业Java环境的开箱即用解决方案( 不推荐Thread
资源的外部管理)。
答案 3 :(得分:-2)
不确定这个,但也许你可以使用aynsctask?它在不同的线程中处理db的东西