簡體   English   中英

Java中的非阻塞ODBC調用

[英]Non-blocking ODBC calls in Java

我使用了非常標准的Java ODBC功能-從池中獲取一個Connection ,創建一個Statement並執行它。

我們的用例是一個游戲,記錄游戲進度-ODBC調用主要是對存儲過程的調用,並且在大多數情況下,沒有返回值。 因此,ODBC調用塊很煩人-游戲已經基於回合制,但是如果數據庫運行緩慢,用戶可以看到更長的暫停時間。

如果我不需要檢查ODBC調用的結果,是否有任何內置功能可以異步執行該語句? 如果不是,那么在不編寫大量代碼的情況下執行此操作的好方法是什么? 我仍然需要捕獲ODBC異常,只要它們發生就可以了。

盡管不完全相同,但這個問題看起來很相關... 可以進行異步jdbc調用嗎?

假設您有一個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或其他工具)時,它將非常有用。
  • 當沒有可用資源時,將應用拒絕策略。 您可以選擇一種內置策略(“拒絕”,“丟棄”,“調用者運行”,“ discardOldest”)或實施自己的策略。
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次。

如果使用的是EJB 3.1,則可以創建@Stateless EJB,並標記方法之一@Asynchronous 這是企業Java環境一個徹頭徹尾的現成解決方案( 外部管理Thread資源不推薦)。

不確定,但是也許可以使用aynsctask? 在不同的線程中處理數據庫的東西

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM