让线程从java中的事件监听器运行?

让线程从java中的事件监听器运行?,java,multithreading,listener,Java,Multithreading,Listener,我有一个程序,它可以创建一个类的数百个实例,每个实例都侦听另一个线程,该线程只需按照常规的定时计划触发一个事件(以便它们都以相同的速度执行)。我希望数百个实例中的每一个都是它自己的线程,这样当触发一个事件时,它们都可以并行工作。对我来说有意义的是让这些类扩展Thread类,然后让这些代码在它们里面 public class IteratorStepListener implements StepEventListener { public void actionPerformed(

我有一个程序,它可以创建一个类的数百个实例,每个实例都侦听另一个线程,该线程只需按照常规的定时计划触发一个事件(以便它们都以相同的速度执行)。我希望数百个实例中的每一个都是它自己的线程,这样当触发一个事件时,它们都可以并行工作。对我来说有意义的是让这些类扩展Thread类,然后让这些代码在它们里面

public class IteratorStepListener implements StepEventListener { 
      public void actionPerformed(ActionEvent e) { 
           start(); 
      } 
 } 

 public void run() { 
      doStuff();
 }

但这似乎不起作用。很明显,我不了解一些基本的东西。这样做的正确方法是什么?

听起来该事件将被触发不止一次。。。但是不能多次启动同一线程

听起来你的监听器应该实现这个接口,但是直接在
actionPerformed
中启动一个线程(或者更好,使用
Executor
,这样它就可以使用线程池)。因此,您可以使用以下方法代替当前的实现:

// Assuming the listener implements runnable; you may want to
// delegate that to a separate class for separation of concerns.
public void actionPerformed(ActionEvent e) {            
    new Thread(this).start(); 
}

我希望数百个实例中的每一个都是它自己的线程,这样当触发一个事件时,它们都可以并行工作

我认为这不是一个好办法

  • 除非有数百个处理器,否则线程不可能全部并行工作。最终,线程将一次运行一个线程(每个处理器一个),或者在处理器之间进行时间切片

  • 每个线程实际上占用了JVM资源的一个重要部分,即使在非活动状态下也是如此。IIRC,默认堆栈大小约为1Mbyte

  • 问题中的示例代码显示了在线程上调用
    start()
    的事件。不幸的是,只能对线程调用一次
    start()
    。一旦线程终止,就不能重新启动它

更好的方法是创建一个具有有界线程池的执行器,并让每个事件都向执行器提交一个新任务。大概是这样的:

ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize,
     keepAliveTime, timeUnit, workQueue);

...

public class IteratorStepListener implements StepEventListener, Runnable { 
    public void actionPerformed(ActionEvent e) { 
        executor.submit(this);
    }

    public void run() { 
        doStuff();
    }
} 

在Java中不能使用这样的线程。这是因为Java线程直接映射到底层OS线程(至少在我所知道的JVM实现上是这样),而OS线程不能像这样扩展。经验法则是,你希望一个应用程序中的线程总数保持在100个左右。几百块就可以了。根据您使用的硬件,通常会有几千个问题

例如,在诸如Erlang之类的语言中,使用您描述的线程是一种有效的实现策略。同时,如果您这次坚持使用Java,那么创建一个共享线程池并将您的任务提交给它而不是允许所有任务同时运行可能是一个不错的选择。在这种情况下,您可以选择适当数量的线程(最佳数量取决于任务的性质。如果您不知道,CPU核心可用时间的数量2是一个良好的开端),并使该数量的任务同时运行


如果您确实需要同时执行所有任务,那么可能会有点复杂,但这也是可行的

好的,第一件事:克服数百个线程将并行运行的观念。在最好的情况下,它们将同时运行,即时间切片。当你进入数百个线程时,你会看到调度算法的方向开始发光;成千上万的人会吸烟,最终会吸起来,你再也找不到线索了

现在,也就是说,我们没有足够的代码来理解您真正在做什么,但我注意到的一点是,您似乎没有创建新的线程。记住,线是一个物体;启动线程的标准方法是

  Thread t = new Thread(Runnable r);
  t.run();
它看起来像是你试图一次又一次地运行同一个线程;这就是疯狂。看一看网上的维基。如果您真的希望有一个单独的线程来处理每个事件,那么您将需要一个类似这样的方案(伪代码):


该解决方案允许多个线程并发执行同一实例。此外,它还可能导致无序事件处理。这不是数百个实例成为它自己的线程,我知道这可能是显而易见的,只是指出这正是我所缺少的。我把我的东西和线搞混了,没什么好处。后来我增加了一名遗嘱执行人,现在一切都顺利多了。谢谢所有回复的人,你帮我省去了几个小时的头痛。“克服你的数百条线程将并行运行的想法”这不像是科幻小说。我们有并行计算,其中一些项目并行运行数十万个处理器。我们有多处理器服务器,以及新的ish 100核心处理器。我们有超级计算机,拥有10万个处理器。欢迎来到未来。(OP可能不是针对这样的硬件,但我们不要传播错误信息。)当您发现一个JVM将在一台高度并行的机器中消耗数千个处理器时,请告诉我。
  Thread t = new Thread(Runnable r);
  t.run();
 processEvents: function
     eventQueue: queue of Events
     event: implements Runnable

     -- something produces events and puts them on the queue

     loop -- forever
     do
         Event ev := eventQueue.front
         new Thread(ev).run();
     od
end -- processEvents