提问者:小点点

维护线程池任务队列的类型信息


我正在通过两本非常有用的书自学并发性:< 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 -如果这是不可避免的,那么有什么坏处吗?这有什么好担心的吗?

谢谢


共2个答案

匿名用户

这与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
 }