我使用非常标准的Java ODBC功能-从池中获取一个Connection,创建一个Statement并执行它。
我们的用例是一个游戏,记录游戏进度- ODBC调用主要是对存储过程的调用,在大多数情况下没有返回值。因此,ODBC调用阻塞的事实是恼人的-游戏已经是基于回合的,但如果DB很慢,用户可能会看到更长的暂停。
如果我不需要检查ODBC调用的结果,是否有任何内置功能可以异步执行该语句?如果没有,有什么好方法可以做到这一点,而不需要编写大量代码?当ODBC异常发生时,我仍然需要捕获它们。
这个问题看起来相关,但并不完全相同。Is asynchronous jdbc call possible?
发布于 2013-02-24 00:31:57
让我们假设您有一个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或其他工具)时,它将非常有用。发布于 2013-02-27 21:45:39
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次。
发布于 2013-02-28 00:41:52
如果您使用的是EJB3.1,则可以创建一个@Stateless EJB,并将其中一个方法标记为@Asynchronous。这是针对Enterprise Java环境的开箱即用的解决方案(不推荐对Thread资源进行外部管理)。
https://stackoverflow.com/questions/14964833
复制相似问题