在ThreadPool的任务队列中维护类型信息

时间:2018-08-25 18:36:37

标签: java scala concurrency jvm futuretask

我正在学习并发的2本书非常有用:
- JVM中的并发性,来自Brian Goetz。
-来自Aleksandar Prokopec的在Scala中学习并发编程

据我所知,我正在尝试构建具有固定线程数的裸ThreadPool。
该线程正在对任务队列进行轮询。
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]
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-如果不可避免,是否有任何不利之处?甚至有问题吗?

谢谢

2 个答案:

答案 0 :(得分:0)

这与JVM中的“类型擦除”有关,该类型被JVM上运行的所有语言所继承。简而言之,泛型由编译器检查,然后被擦除,因此,如果要混合类型的集合,则集合的类型参数必须是所有可能类的超类。是的,当您从集合中检索数据时,将剩下超类。

我认为Shapeless的HList可让您在列表中保留多种类型。

否则,您需要投射。如果需要,我可以使用类似于以下的功能:

def dequeue[T](tasks: mutable.Queue[MyFutureTask[Any]]) = tasks.dequeue().asInstanceOf[MyFutureTask[T]]

答案 1 :(得分:0)

我完全不知道为什么您的队列根本不需要知道返回类型。 只需使其在08-26 08:33:09.596 6547 6563 I art : Starting a blocking GC NativeAlloc 08-26 08:33:09.596 6547 6563 I art : Starting a blocking GC NativeAlloc 08-26 08:33:09.685 20256 20374 I art : Starting a blocking GC NativeAlloc 08-26 08:33:09.685 20256 20374 I art : Starting a blocking GC NativeAlloc 08-26 08:33:09.710 1736 2376 I art : Starting a blocking GC NativeAlloc 08-26 08:33:09.710 1736 2376 I art : Starting a blocking GC NativeAlloc 上运行即可:

Runnables