Я изучаю параллелизм с двумя очень полезными книгами:
- Параллелизм в JVM , от Брайана Гетца.
- Обучение параллельному программированию в Scala , от Александар Прокопец.
В качестве проверки, насколько мне известно, я пытаюсь создать чистый ThreadPool с фиксированным числом потоков.
Эти потоки опрашивают очередь задач.
ThreadPool предоставляет мне метод для вставки задач в очередь, возвращая MyFutureTask[T]
, который, я надеюсь, является эмуляцией фактического FutureTask[T]
в Java, чтобы я мог получить значение позже.
def addTask[T](theTask: () => T): MyFutureTask[T] = queue.synchronized {
val myFutureTask: MyFutureTask[T] = new MyFutureTask[T] {
override val task: () => T = theTask
}
queue.enqueue(myFutureTask)
queue.notify()
myFutureTask
}
Если меня не волнует возвращаемое значение заданий, которые я отправляю (т.е. Runnable), тогда у меня может быть правильный тип для очереди задач, а именно MyFutureTask[Unit]
:
private val queue = mutable.Queue[MyFutureTask[Unit]]()
Однако, когда задачи возвращают значение, которое я позже хочу получить, для этого потребуется, чтобы очередь задач не имела правильного типа, так как мне нужно было бы передать в ThreadPool несколько задач, каждая с различным типом возврата ( задача 1: () => String
, задача 2: () => Int
, задача 3: () => SomeProperType
...), что приведет к:
private val tasks = mutable.Queue[MyFutureTask[_]]()
Это заставляет меня чувствовать себя неловко, так как в Scala все, что не напечатано, осуждается.
Итак, мои вопросы:
1 - Я сказал что-то не так выше? Я пропустил какой-то шаг импорта? Или это совсем не правильный подход?
2 - Неизбежно ли, что очередь задач не имеет правильного типа в реальных реализациях ThreadPool?
3 - Если это неизбежно, есть ли у него недостатки? Это даже беспокойство?
Спасибо