подход с использованием потокового программирования - PullRequest
1 голос
/ 02 марта 2010

Это мой сценарий.

У меня есть пул частот, и мой BaseStation должен выбрать одну из них. Критическая секция для BaseStation - это фаза, когда она входит в выбор частоты. После выбора частот управление возвращается к основному классу BaseStation и возобновляет генерацию запроса. В то же время, то есть, как только он выйдет из своего критического участка, выбранная частота перейдет в состояние использования на определенный период времени, который будет определяться случайными часами. Таким образом, эта частота будет недоступна для любого другого запроса, который происходит в промежуточный период. Когда время использования частоты истекло, оно просто снова устанавливает свой статус как доступный. Таким образом, часть взаимного исключения для BaseStation предназначена только для выбора частоты, после ее завершения функциональность BaseStation и время использования частоты работают параллельно.

Как я до сих пор кодировал: у меня есть три класса BaseStation, CriticalSection и UseFrequency. BaseStation вызывает функцию в CriticalSection для выбора частоты, когда частота выбрана, у меня есть функция, которая запускает поток в другом классе для использования частоты, а затем возвращает управление на BaseStation вскоре после:

UseFrequency freqInUse = new UseFrequency; 
freqInUse.start(); 
return 1; 

Но как только поток останавливается, классу CriticalSection необходимо обновить некоторые переменные, я запутался, как вернуть управление обратно в средний класс. Нужно ли использовать два потока?

Ответы [ 5 ]

4 голосов
/ 02 марта 2010

Я не уверен, что ваш вопрос (так что я вроде как догадался!), Но один из вариантов - обернуть Apache GenericObjectPool для хранения ваших Frequency объектов и вызвать borrowObject() для удаления Frequency из пула и указать, что он «используется». После вызова borrowObject() вы также можете запланировать задачу (например, с ScheduledExecutorService) на вызов returnObject() в какой-то момент в будущем, что сделает Frequency снова доступным для других потоков.

public class FrequencyPool {
  private final GenericObjectPool objPool = ...
  private final ScheduledExecutorService timerService = ...
  private final Random random = new Random();

  public Frequency takeFrequency() {
    final Frequency freq = (Frequency) objPool.borrowObject(); // Will block

    // Return frequency to underlying object pool after a random time.
    timerService.schedule(new Callable<Void>{
      public Void call() {
        objPool.returnObject(freq);
      }
    }, random.nextInt(10), TimeUnit.SECONDS);

    return freq;
  }
}
2 голосов
/ 02 марта 2010

Простейшим способом управления параллелизмом для чего-то подобного является, вероятно, ReadWriteLock ( ReentrantReadWriteLock - реализация). Во время выбора частоты вы должны заблокировать блокировку записи, а затем разблокировать, когда закончите. Нормальное использование просто получит блокировки чтения. Это обеспечивает взаимное исключение при выборе частоты, но в противном случае используется одновременно.

Более общее решение с более детальным контролем над объединенным набором ресурсов может быть построено с семафором .

1 голос
/ 02 марта 2010

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

0 голосов
/ 04 марта 2010

Чтобы вы вернули управление обратно в вызывающий класс критической секции, используйте Executor для выполнения вашего потока. Например:

Blockquote ExecutorService executor = Executors.newSingleThreadExecutor ();

    Future<?> future = executor.submit(//submit frequency thread runnable object);

    try {
        future.get();
        //do critical section update
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    executor.shutdown();
0 голосов
/ 02 марта 2010

Теперь я понимаю вопрос. Использование наблюдаемой модели было бы хорошим способом сделать это. Вот пример, который мне нравится из Javaworld: http://www.javaworld.com/javaworld/javatips/jw-javatip29.html

...