我正在学习并发的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-如果不可避免,是否有任何不利之处?甚至有问题吗?
谢谢
答案 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