Многопоточное приложение Java - как динамически отменять объекты Futures - PullRequest
5 голосов
/ 26 марта 2010

Я думаю, что это распространенный сценарий для многопоточных приложений Java, поэтому я попытаюсь описать его здесь.

В моем Java-приложении есть объект threadExecutor , который определяет пул из 5 потоков.

ExecutorService threadExecutor = Executors.newFixedThreadPool(5);

Метод sendCallables отвечает за назначение списка заданий исполнителю.
Я отслеживаю Список с ObjectX . Таким образом, я могу ссылаться на список Фьючерсов, если Пользователь хочет прервать / отменить Потоки. Примерно так:

Map<ObjectX, List<Future<String>>> map = new HashMap<ObjectX, Future<String>>();

public void sendCallables(ObjectX referenceObj, List<Callable<String>> list) {
    ...
    List<Future<String>> futureList = new ArrayList<Future<String>>();
    for(Callable<String> myCallableJob : list) {
        Future<String> future = threadExecutor.submit(myCallableJob);
        futureList.add(future);
    }
    ...
    map.add(referenceObj, futureList);
    ...
}

public void cancelFutures(ObjectX referenceObj) {
    ...
    List<Future<String>> list = map.get(referenceObj);
    for(Future<String> future : list) {
        future.cancel();
    }
    map.remove(referenceObj);
    ....
}

Пока все хорошо.

Теперь есть случаи, когда больше не нужно выполнять представленные задачи .
В этих ситуациях приложение об отмене задач должно приниматься интеллектуально / автоматически приложением.
Примеры таких случаев можно найти в веб-приложении, когда истекает сеанс пользователя или когда конкретный поток (связанный с представленными задачами) заканчивается до выполнения всех заданий.

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

Мне интересно, есть ли лучший способ сделать это.

Я думал в WeakHashMap , чтобы иметь возможность очистить карту, как только на referenceObj больше не ссылается приложение, но это не останавливает выполнение Futures, поскольку мне все еще нужно вызывать. cancel () для них (своего рода eventHandler, связанный с WeakHashMap, метод remove (Object)?)

Ответы [ 2 ]

3 голосов
/ 26 марта 2010

Я думаю, что решение, которое вы предлагаете, довольно хорошее. Если вы действительно, действительно хотите получить отмену из referenceObj, собирающего мусор, вы можете использовать комбинацию WeakReference и ReferenceQueue.

Сделайте так, чтобы один из них был объявлен в вашем классе помощника выполнения.

ReferenceQueue<ObjectX> refQ = new ReferenceQueue<ObjectX>();

Делайте это каждый раз, когда отправляется пакет задач

new WeakReference<ObjectX>( referenceObj, refQ ).enqueue();

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

while (true)
{
    // this blocks
    ObjectX referenceObj = refQ.remove().get();
    cancelFutures( referenceObj );
}
0 голосов
/ 26 марта 2010

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

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

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

...