2012-06-04 2 views
4

Я хочу вызвать функцию HashSet add с некоторой задержкой, но без блокировки текущего потока. Есть простое решение, чтобы достичь что-то вроде этого:Как сделать вызов функции отложенной неблокирующей функции

Utils.sleep(1000, myHashSet.add(foo)); //added after 1 second 
//code here runs immediately without delay 
... 
+1

Прямые ответы на ваш вопрос ниже. Но то, что пытаются сделать, кажется довольно неестественным, что предполагает, что, возможно, вам стоит искать совершенно другое решение. Вы хотите предоставить еще один контекст, почему вы хотите отложить добавление? – Jochen

+0

Я использую [Storm] (https://github.com/nathanmarz/storm) для реализации искателя. URL-адреса для обхода генерируются шаблоном, содержащим идентификатор потока и идентификатор платы. Характер искателя позволяет обрабатывать только один URL-адрес для каждой платы. Мой HashSet содержит все идентификаторы плат, которые в настоящее время могут свободно сканировать. Сканирование одного URL-адреса может завершиться по разным причинам (поток был удален, 404, ...). Некоторые причины позволяют повторить сканирование. Информация об этих причинах сохраняется в БД, которая не блокируется, поэтому должна быть какая-то задержка перед тем, как решить, повторить или нет. – Thomas

+0

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

ответ

3

Вы можете использовать ScheduledThreadPoolExecutor.schedule:

ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1); 

exec.schedule(new Runnable() { 
      public void run() { 
       myHashSet.add(foo); 
      } 
    }, 1, TimeUnit.SECONDS); 

Он будет выполнять код после того, как 1 секунду в отдельном потоке. Однако будьте осторожны при одновременных модификациях myHashSet. Если вы одновременно изменяете коллекцию из другого потока или пытаетесь перебрать его, у вас могут быть проблемы, и вам нужно будет использовать блокировки.

9

Равнина раствор ванили будет:

new Thread(new Runnable() { 
     public void run() { 
      try { Thread.sleep(1000); } 
      catch (InterruptedException ie) {} 
      myHashSet.add(foo); 
     } 
    }).start(); 

Там намного меньше, что происходит за кулисами здесь, чем с ThreadPoolExecutor. TPE может быть удобнее контролировать количество потоков, но если вы отключаете много потоков, которые спят или ждут, ограничение их числа может повредить производительность намного больше, чем помогает.

И вы хотите синхронизировать на myHashSet, если вы еще не обработали это. Помните, что вам нужно синхронизировать везде, чтобы это не приносило пользы. Есть другие способы справиться с этим, например Collections.synchronizedMap или ConcurrentHashMap.

Смежные вопросы