我正在通过两本非常有用的书自学并发性:< br >-JVM中的并发性,作者是Brian Goetz。< br> -学习Scala中的并发编程,来自Aleksandar Prokopec。
据我所知,我正在尝试用固定数量的线程构建一个裸线程池
此线程正在轮询任务队列
ThreadPool为我提供了一种在队列中插入任务的方法,返回一个MyFutureTask[T]
,我希望这是对java中实际FutureTask[T]
的模拟,以便我以后可以检索该值。
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]
:私有val队列=mutable. Queue[MyFutureTask[Unit]]()
然而,当任务返回一个我稍后要检索的值时,这将要求任务队列的类型不正确,因为我需要向ThreadPool提交多个任务,每个任务都具有不同的返回类型(task1:()=
< code >私有val tasks = mutable。Queue[MyFutureTask[_]]()
这让我感到不安,因为在 Scala 中,所有未键入的内容都是不受欢迎的。
所以我的问题是:< br> 1 -我上面说错什么了吗?我错过了什么重要的步骤吗?还是这根本就不是正确的做法?< br> 2 -在实际的线程池实现中,任务队列不具有正确的类型是不可避免的吗?< br> 3 -如果这是不可避免的,那么有什么坏处吗?这有什么好担心的吗?
谢谢
这与JVM中由运行在JVM上的所有语言继承的“类型擦除”有关。简而言之,泛型由编译器检查,然后被擦除,所以如果你想要一个混合类型的集合,该集合的类型参数必须是所有可能类的超类。是的,当你从集合中检索数据时,你会剩下超类。
我认为Shapeless的HList允许在一个列表中保存多个类型。
否则,您需要投射。如果必须,我使用类似于下面的函数:
def dequeue[T](tasks: mutable.Queue[MyFutureTask[Any]]) = tasks.dequeue().asInstanceOf[MyFutureTask[T]]
我不明白为什么你的队列需要知道返回类型。只需让它在< code>Runnables上运行:
def addTask[T](theTask: () => T): Future[T] = {
val result = Promise[T]()
val myFutureTask: Runnable = new Runnable {
override val run() {
result.complete(Try { theTask() })
}
}
queue.synchronized {
queue.enqueue(myFutureTask)
queue.notify()
}
result.future
}