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

标签 java scala concurrency jvm futuretask

我正在通过两本非常有帮助的书自学并发:
- JVM 中的并发,来自 Brian Goetz。
- 学习 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]:
私有(private) val 队列 = mutable.Queue[MyFutureTask[Unit]]()

但是,当任务返回我稍后想要检索的值时,这将要求任务队列没有正确的类型,因为我需要向 ThreadPool 提交多个任务,每个任务都有不同的返回类型(task1 : () => String、task2: () => Int、task3: () => SomeProperType ...),这将导致:

私有(private) val 任务 = mutable.Queue[MyFutureTask[_]]()

这让我感到不安,因为在 Scala 中,所有未键入的内容都会被拒绝。

所以我的问题是:
1 - 我上面说的有错吗?我错过了一些导入步骤吗?或者这根本不是正确的方法?
2 - 在实际的ThreadPool实现中任务队列没有正确的类型是不可避免的吗?
3 - 如果这是不可避免的,它有什么缺点吗?这还值得担心吗?

谢谢

最佳答案

这与 JVM 中运行的所有语言都继承的“类型删除”有关。简而言之,泛型由编译器检查,然后被删除,因此如果您想要混合类型的集合,则该集合的类型参数必须是所有可能类的父类(super class)。是的,当您从集合中检索数据时,您将获得父类(super class)。

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

否则,您需要施放。如果必须的话,我会使用与此类似的函数:

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

关于java - 维护线程池任务队列的类型信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52020195/

相关文章:

java - 接下来在已经运行的Android ViewPager中插入新的Fragment

json - 根据其他字段指定的类型读取 JSON 字段

scala - 在 scala 中模拟会生成 java.lang.NoSuchMethodException

java - volatile 如何使我的类线程安全?

java - 如何在 MockClientHttpRequest/Response 中使用 RestTemplate xml 文件

Java 我收到错误但它仍然运行

scala - 如何在 Scala 中查找集合中的连续元素

java - 如果我在同步块(synchronized block)中使用等待,则 IllegalMonitorStateException 的原因

java - ConcurrentHashMap中,如何同步更新?

java - 如何上传视频到客户自己的youtube channel