java - 有没有更优雅的方式来启动基于列表的线程?

标签 java multithreading dynamic scheduling

我的程序/类正在获取需要在并行线程中运行的类列表(例如 C-1() 到 C-100())。每个都是它自己的类,并且有它自己的可执行文件,所以我不需要编译,只需运行。虽然每个类都有一个参数,但每个类内部的逻辑可能非常不同。因此,不可能多次启动一个带有参数的类。

类列表是可变的。可能有一个类别 (C-3()) 或多个类别 (C-1()、C-2()、C-4()、C-3()),并且它们可以按或不按任何顺序。

我使用了带有循环和 switch 语句的批量方法,但编写 100 个这样的代码似乎不必要地复杂,而且坦率地说,看起来很糟糕。但它有效,最坏的情况下,也能完成工作。但这让我很烦恼。

case ("C-1")
{
   new C-1("parm").start();
}
etc .... x 100

lambda 函数可能会让我到达那里,但它超出了我的经验。

我不想把它掏空。这看起来既效率低下,又可能成为性能 killer 。

在完美的世界中,我会动态地从列表中提取该项目并启动它。但我不知道如何动态替换对象名。我不想用任何巧妙的链接来减慢速度。我的专业知识不足以解决这个问题。

最好添加一些内容,这样如果列表小于 10,它就会在同一个线程中运行它,并且只有在列表超过 10 时才进行大规模并行。但这也不属于我的专业知识。

最佳答案

In a perfect world, I would dynamically pull the item from the list and launch it. But I cant figure out how to replace the objectname dynamically.

这种动态操作的Java子系统和技术称为“反射”。 java.lang.Class 类在这里起着核心作用,其余大部分关键类都来自包 java.lang.reflect。反射允许您获取通过名称标识的类的 Class 对象,创建该类的实例,并调用这些实例上的方法。

如果您的 C-* 类都具有定义 start() 方法(Thread?)的公共(public)父类(super class)或接口(interface),那么您甚至可以执行普通方法调用反射。

假设您想要动态实例化的所有类都提供接受相同参数类型并且想要向其传递相同参数值的构造函数,您可以使用它来节省编写 100 路条件或一百个不同的适配器类或类似的,适合您的情况。从原理上讲,它的工作原理如下:

  • 获取或创建所需类的完全限定类名,例如 className

  • 获取对应的Class

    Class<?> theClass = Class.forName(className);
    
  • 获取表示您要使用的构造函数的构造函数。在您的示例中,构造函数采用与 String 类型兼容的单个参数。如果声明的参数类型实际上是 String 本身(而不是 ObjectSerialized,或...),那么就会像这样完成所以:

    Constructor<?> constructor = theClass.getConstructor(String.class);
    
  • 有了它,您就可以实例化该类:

    Object theInstance = constructor.newInstance("parm");
    

如上所述,您的路径取决于是否存在共同的父类(super class)型。如果有的话就可以

  • 强制转换实例并正常调用其方法:

    ((MySupertype) theInstance).start();
    

否则,您还需要以反射方式调用该方法。由于感兴趣的方法不带任何参数,这在某种程度上简化了:

  • 获取Method实例。

    Method startMethod = theClass.getMethod("start");
    
  • 调用对象上的方法

    startMethod.invoke(theInstance);
    

你还提到,

It would also have been nice to add something so that if the list is less than 10, it would run it in the same thread and only go massively parallel if it was above that.

以上内容与启动运行代码的新线程没有任何直接关系。如果这是 start() 方法自己执行的操作(例如,如果涉及的类将 java.lang.Thread 作为父类(super class)),那么避免的唯一选择每个运行在自己线程上的对象都使用不同的方法。

另一方面,如果您从在一个线程中运行的所有内容开始并希望实现并行化,则可以使用 @PaulProgrammer's answer 中所述的线程池。是一个很好的方法。请注意,如果任务彼此独立(正如您的描述所示),那么尝试确保它们全部同时运行就没有多大意义。线程数量多于运行它们的核心数量并不能真正帮助您,线程池对于排队任务以进行并行执行非常有用。当然,检查列表的 size() 来决定是将任务发送到线程池还是直接运行它们会很简单。

关于java - 有没有更优雅的方式来启动基于列表的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57498008/

相关文章:

java - 如何在 2 种方法中使用 int

java - 检查数据库中是否存在日期

2D游戏中Java swing渲染现象

java - 动态类加载在运行时失败

java - 切换主题时如何考虑变化?

java - Java SettableFuture 和 ListenableFuture 的 C# 等价物是什么?

c - 是否有可能有效地并行对 4 种不同的密码模式进行暴力攻击?

c++ - 让多线程程序的两个 "deep"部分相互通信的模式是什么?

java - 正确使用同步单例?

forms - Laravel 5 动态表单验证