Java中的非阻塞ODBC调用

Mr.*_*Boy 1 java jdbc java-6

我使用非常标准的Java ODBC功能 - Connection从池中获取a ,创建Statement并执行它.

我们的用例是游戏,记录游戏进度 - ODBC调用主要是对存储过程的调用,并且在大多数情况下没有返回值.因此,ODBC调用阻塞的事实很烦人 - 游戏已基于回合,但如果数据库速度慢,用户可以看到更长的暂停时间.

如果我不需要检查ODBC调用的结果,是否有任何内置功能来异步执行语句?如果没有,在没有编写大量代码的情况下,这样做的好方法是什么?如果发生ODBC异常,我仍然需要捕获它们.

这个问题虽然不相同但看起来有意义... 异步jdbc调用是否可行?

eri*_*son 9

我们假设你有一个OdbcCaller:

public class OdbcCaller {

public void callODBC() {
    // call ODBC directly
    // ...
}
Run Code Online (Sandbox Code Playgroud)

您可以将其包装在可运行的任务中,并将任务提交到线程池以使其以异步方式执行:

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.
}
Run Code Online (Sandbox Code Playgroud)

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());
Run Code Online (Sandbox Code Playgroud)

ThreadPoolExecutor具有高度可配置性,并且在JavaDoc中有记录,您可能需要先阅读它.

以下是根据我的经验对线程池配置的一些建议:

  • 正确的线程池大小取决于场景,您可能需要运行一些测试来调整它.
  • 工作队列用于在没有可用的工作线程时缓存任务.一个无界的队列不是一个好主意,因为你可能会耗尽你的记忆.
  • 提供a ThreadFactory并给线程一个有意义的名称是一个好习惯.当您需要检查线程状态(使用jstack或其他工具)时,它将非常有用.
  • 当没有可用资源时,将应用拒绝策略.您可以选择其中一个内置策略(拒绝,丢弃,调用者运行,discardOldest),或实施您自己的策略.