简体   繁体   English

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

[英]Is there a more elegant way to launch a thread based on a list?

My program/class is getting a list of classes (eg C-1() through C-100()) that need to be run in parallel threads. 我的程序/类正在获取需要在并行线程中运行的类列表(例如C-1()至C-100())。 Each one is its own Class and has its own executable so i don't need to compile, just run. 每个都是自己的类,并且都有自己的可执行文件,因此我不需要编译,只需运行即可。 While each class takes a parameter, the logic inside each can be very different. 虽然每个类都带有一个参数,但每个类内部的逻辑可能非常不同。 So no hope of launching one class with a parameter multiple times. 因此,没有希望多次启动带有参数的类。

The list of classes is variable. 类列表是可变的。 There may be one class (C-3()) or multiple (C-1(),C-2(),C-4(),C-3()) and they may or may not be in any order. 可能有一个类别(C-3())或多个类别(C-1(),C-2(),C-4(),C-3()),它们的顺序可能相同也可能不相同。

I have used the bulk method with a loop and a switch statements but coding 100 of those seems unnecessarily complex and frankly just looks bad. 我在循环和switch语句中使用了bulk方法,但是对其中的100条进行编码似乎不必要地复杂,并且坦率地说看起来很糟糕。 But it works and worst case, will do the job. 但这是可行的,并且在最坏的情况下会胜任。 But it bothers me. 但是,这困扰着我。

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

the lambda functions might get me there but its outside my experience. lambda函数可能会让我到达那里,但超出了我的经验。

I didnt want to shell it out. 我不想掏空它。 That seems both inefficient and potentially a performance killer. 这似乎既低效又可能是性能杀手。

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. 但是我不知道如何动态替换对象名称。 I dont want to slow it down with any clever linking. 我不想通过任何聪明的链接来减慢它的速度。 My expertise isnt enough to tackle that one. 我的专业知识不足以解决这一问题。

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. 添加一些东西也很不错,如果列表少于10个,它将在同一线程中运行,并且如果列表大于10,则只能大规模并行运行。 But thats also outside my expertise. 但是那也不是我的专长。

The accepted best way to approach this problem is to use a ThreadPool . 解决此问题的最佳方法是使用ThreadPool The idea is that you will spawn a known number of threads, and use those worker threads to work through a queue of tasks. 这个想法是,您将产生一个已知数量的线程,并使用这些工作线程来处理一系列任务。 The threads themselves can be reused, preventing the overhead of thread creation. 线程本身可以重用,从而避免了创建线程的开销。

https://howtodoinjava.com/java/multi-threading/java-thread-pool-executor-example/ https://howtodoinjava.com/java/multi-threading/java-thread-pool-executor-example/

package com.howtodoinjava.threads;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class ThreadPoolExample
{
    public static void main(String[] args)
    {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);

        for (int i = 1; i <= 5; i++)
        {
            Task task = new Task("Task " + i);
            System.out.println("Created : " + task.getName());

            executor.execute(task);
        }
        executor.shutdown();
    }
}

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. 但是我不知道如何动态替换对象名称。

The Java subsystem and technique for this kind of dynamic operation is called "reflection". 用于这种动态操作的Java子系统和技术称为“反射”。 The java.lang.Class class plays a central role here, with most of the rest of the key classes coming from package java.lang.reflect . java.lang.Class类在这里起着核心作用,其余大多数关键类来自于包java.lang.reflect Reflection permits you to obtain the Class object for a class you identify by name, to create instances of that class, and to invoke methods on those instances. 反射允许您为通过名称标识的类获取Class对象,创建该类的实例,并在这些实例上调用方法。

If your C-* classes all have a common superclass or interface that defines the start() method ( Thread ?) then you could even perform normal method invocation instead of reflective. 如果您的C- *类都具有定义start()方法( Thread ?)的公共超类或接口,那么您甚至可以执行常规方法调用而不是反射方法。

Provided that all the classes you want to dynamically instantiate provide constructors that accept the same parameter type and to which you want to pass the same argument value, you can use it to save writing 100-way conditionals, or a hundred different adapter classes, or similar, for your case. 假设您要动态实例化的所有类都提供了接受相同参数类型并且要将相同参数值传递给的构造函数,则可以使用它来保存编写100向条件或一百个不同适配器类的过程,或者类似的,对于您的情况。 Schematically, it would work along these lines: 从原理上讲,它将遵循以下原则:

  • obtain or create a fully-qualified class name for the wanted class, let's say className . 获取或创建所需类的标准类名称,例如className

  • obtain the corresponding Class 获取相应的Class

     Class<?> theClass = Class.forName(className); 
  • Obtain a Constructor representing the constructor you want to use. 获取一个Constructor代表您要使用的构造函数。 In your example, the constructor takes a single parameter of a type compatible with String . 在您的示例中,构造函数采用与String兼容类型的单个参数。 If the declared parameter type is in fact String itself (as opposed to Object or Serializable , or ...) then that would be done like so: 如果声明的参数类型实际上是String本身(而不是ObjectSerializable或...),则可以这样做:

     Constructor<?> constructor = theClass.getConstructor(String.class); 
  • Having that in hand, you can instantiate the class: 掌握了这一点,您可以实例化该类:

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

Your path from there depends on whether there is a common supertype, as mentioned above. 如上所述,您从那里开始的路径取决于是否存在一个共同的超类型。 If there is, then you can 如果有,那么你可以

  • Cast the instance and invoke the method on it normally: 强制转换实例并在其上正常调用方法:

     ((MySupertype) theInstance).start(); 

Otherwise, you'll need to invoke the method reflectively, too. 否则,您还需要反射地调用该方法。 This is somewhat simplified by the fact that the method of interest does not take any parameters: 所关注的方法不带任何参数的事实对此进行了某种程度的简化:

  • Obtain a Method instance. 获取Method实例。

     Method startMethod = theClass.getMethod("start"); 
  • Invoke the method on your object 在对象上调用方法

     startMethod.invoke(theInstance); 

You also mention, 您还提到

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. 添加一些东西也很不错,如果列表少于10个,它将在同一线程中运行,并且如果列表大于10,则只能大规模并行运行。

None of the above has anything directly to do with starting new threads in which to run your code. 以上都不是与启动新线程来运行代码直接相关的。 If that's something that the start() methods will do themselves (for example, if the classes involved have java.lang.Thread as a superclass) then the only alternative for avoiding each object running on its own thread is to use a different method. 如果那是start()方法将自己完成的事情(例如,如果所涉及的类具有java.lang.Thread作为超类),则避免每个对象在其自己的线程上运行的唯一替代方法是使用不同的方法。

On the other hand, if you're starting from everything running in one thread and looking to parallelize, then using a thread pool as described in @PaulProgrammer's answer is a great way to go. 另一方面,如果您从在一个线程中运行的所有内容开始并希望进行并行化,那么按照@PaulProgrammer的答案中所述使用线程池是一个不错的方法。 Note well that if the tasks are independent of each other, as seems the case from your description, then there's not much point in trying to ensure that they all run concurrently. 请注意,如果任务是相互独立的(如您的描述所示),那么尝试确保它们同时运行就没有多大意义。 More threads than you have cores to run them on does not really help you, and a thread pool is useful for queueing up tasks for parallel execution. 线程数多于您要在其上运行的内核并不能真正帮到您,线程池对于排队任务以并行执行很有用。 Of course it would be simple to check the size() of your list to decide whether to send tasks to a thread pool or to just run them directly. 当然,检查列表的size()以确定是将任务发送到线程池还是直接运行任务将很简单。

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

相关问题 有没有一种方法可以更优雅地编写此“ if”列表? - Is there a way to write this “if” list in a more elegant way? 更优雅的实现方式 - More elegant way to implement 根据其他值设置对象的更优雅的方法 - A more elegant way of setting up an object based on other values 编码二传手的更优雅方式 - More Elegant Way of Coding a Setter 有没有更优雅的方式来编写这个构建器? - is there a more elegant way to code this builder? 是否有比嵌套匿名Runnable更好的在JavaFX Application线程上执行TimerTasks的方法? - Is there a more elegant way of executing TimerTasks on JavaFX Application thread than nested anonymous Runnable? Java:有没有更优雅的方法可以使用 reduce 从现有列表中提取新列表? - Java: is there more elegant way to extract a new list from an existing list using reduce? 有没有更优雅的方法来使用java 8从列表中获取随机未使用的项? - Is there a more elegant way to get random not used item from list using java 8? 一种遍历列表以比较两个相邻元素的更优雅的方法 - A more elegant way to iterate through a list to compare 2 elements next to one another 比较Java中对象的更优雅方法 - More elegant way of comparing objects in Java
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM