Избегайте тайм-аута соединения при использовании нескольких потоков и пула соединений

Я разбиваю операцию базы данных только для чтения на несколько частей (каждая из которых считывает подмножество очень большого объема данных, анализирует их и записывает результаты в файл на диске).

Каждый фрагмент выполняет выбор (в таблицу данных) в новом потоке .net (с использованием делегата и BeginInvoke).

Существует больше подмножеств данных, чем доступных соединений в пуле, поэтому, когда у меня заканчиваются соединения, до того, как первое будет выпущено, последующие запросы на соединение ставятся в очередь... до тех пор, пока не истечет время ожидания соединения, а затем я получаю исключение тайм-аута.

Как мне либо: A) запретить исключение соединения с тайм-аутом, когда все соединения в пуле используются, либо B) определить, что все они используются, прежде чем я даже попрошу еще одно, чтобы я мог подождать, пока одно из них не будет доступно, прежде чем запрашивать ?


person Charles Bretana    schedule 02.12.2008    source источник


Ответы (1)


Два решения:

A) Настройте пул соединений с тайм-аутом в несколько дней. Это заблокирует ожидающие задачи до тех пор, пока соединение не будет возвращено. Недостаток: это не будет работать, когда задача зависнет.

Б) Используйте пул потоков и рабочую очередь. Пул потоков должен иметь тот же размер, что и пул соединений (т. е. одно соединение на поток). Поместите всю работу в очередь и пусть задачи извлекают рабочие элементы из очереди, пока очередь не опустеет.

Псевдокод для решения B:

public class Setup
    connPool = createConnectionPool(100);
    queue = createWorkQueue();
    putAllWorkItemsInQueue(queue);
    for (int i=0; i<connPool.size(); i++) {
        t = new WorkerThread(queue)
        list.add(t);
        t.start();
    }
    while (queue.size() != 0) {
        Thread.sleep(1000);
    }
    for (thread in list) {
        thread.interrupt();
    }

public class WorkerThread
    run() {
        while (true) {
            try {
                workUnit = queue.get(); // This blocks
                process(workUnit);
            } catch (InterruptedException e) {
                break;
            }
        }
    }
person Aaron Digulla    schedule 02.12.2008
comment
с опцией B этот пул потоков устанавливается на максимум 100 потоков (поскольку пул соединений установлен на 100), а затем в моем коде, где я вызываю BeginInvoke(), я зависаю, когда все 100 потоков используются, до тех пор, пока ранее использованный поток завершается и возвращается в мой пул потоков? - person Charles Bretana; 02.12.2008