简体   繁体   English

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

[英]Mantaining type information on the queue of tasks of a ThreadPool

I am self learning concurrency with the 2 very helpful books: 我通过2本书非常自学并发:
- Concurrency in the JVM , from Brian Goetz. -来自Brian Goetz 的JVM中的并发
- Learning Concurrent Programming in Scala , from Aleksandar Prokopec. -从Aleksandar Prokopec 学习Scala中的并发编程

As a test to my knowledge, I am trying to build a bare ThreadPool with a fixed number of threads. 据我所知,我正在尝试构建一个具有固定数量线程的裸ThreadPool。
This threads are polling on a queue of tasks. 该线程正在对任务队列进行轮询。
The ThreadPool provides me a method to insert tasks in a queue, returning a MyFutureTask[T] , which I hope is an emulation of the actual FutureTask[T] in java, so that I can retrieve the value later. 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
 }

If I do not care about the return value of the tasks I submit (ie Runnable) then I can have a proper type for the queue of tasks, namely MyFutureTask[Unit] : 如果我不在乎我提交的任务的返回值(即Runnable),则可以为任务队列使用适当的类型,即MyFutureTask[Unit]
private val queue = mutable.Queue[MyFutureTask[Unit]]()

However, when the tasks return a value that I later want to retrieve, this would require the tasks queue not to have a proper type, as I would need to submit to the ThreadPool multiple tasks, each with a different return type ( task1 : () => String , task2: () => Int , task3: () => SomeProperType ... ), which would lead to: 然而,当任务返回,我以后要检索值,这将需要的任务队列不是有一个正确的类型,因为我需要提交给线程池多个任务,每一个不同的返回类型(TASK1: () => String ,task2: () => Int ,task3: () => SomeProperType SomeProperType ...),这将导致:

private val tasks = mutable.Queue[MyFutureTask[_]]()

This leaves me uneasy, as in Scala everything that is not typed is frowned upon. 这让我感到不安,因为在Scala中,所有未键入的内容都被皱眉了。

So my questions are: 所以我的问题是:
1 - Have I said anything wrong above? 1-我上面说错了吗? Am I missing some import step? 我是否缺少一些导入步骤? Or is this not the correct approach at all? 还是这根本不是正确的方法?
2 - Is it unavoidable for the queue of tasks not to have a proper type in the actual ThreadPool implementations? 2- 不可避免的是,在实际的ThreadPool实现中,任务队列没有正确的类型吗?
3 - If it is unavoidable, are there any disadvantages to it? 3-如果不可避免,是否有任何不利之处? Is that even a concern? 这甚至是一个问题吗?

Thanks, 谢谢,

This is related to "type erasure" in the JVM that is inherited by all the languages that run on the JVM. 这与JVM中的“类型擦除”有关,该类型被JVM上运行的所有语言所继承。 In short, generics are checked by the compiler and then they are erased, so if you want a collection of mixed type, the collection's type-parameter must be the super-class of all the possible classes. 简而言之,泛型由编译器检查,然后被擦除,因此,如果要混合类型的集合,则集合的类型参数必须是所有可能类的超类。 And yes, when you retrieve the data from the collection you are left with the super class. 是的,当您从集合中检索数据时,您将剩下超类。

I think that Shapeless's HList let you keep multiple types in a list. 我认为Shapeless的HList可让您在列表中保留多种类型。

Otherwise, you need to cast. 否则,您需要进行投射。 If I have to, I use a function similar to this: 如果需要,我可以使用类似于以下的功能:

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

I don't see why your queue needs to know about a the return type at all. 我不明白为什么您的队列根本不需要知道返回类型。 Just make it operate on Runnables : 只需使其在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
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM