【问题标题】:Creating infinite short lived threads创建无限的短命线程
【发布时间】:2018-02-21 14:52:36
【问题描述】:

我有一个 javafx 应用程序,我正在使用 FX 线程中调用阻塞方法

new Thread(() -> doWork(someParam)).start();

我希望用户能够单击调用方法的按钮,但不会冻结 UI。我还希望点击次数等于方法调用次数。

这目前解决了我的问题,但是这会导致内存使用方面的任何问题吗?我知道线程最终会死掉,垃圾收集器会对其采取行动,但这是不好的做法吗?

此外,当创建一个新线程时,它会被分配一个新的递增线程 ID。 线程ID溢出时会不会有问题?

【问题讨论】:

  • 启动线程很慢。否则你会没事的,当线程对象和资源变得无法访问时,完成的线程和它们占用的所有资源都将被垃圾收集。在任何情况下,使用线程池:ExecutorService threadPool = Executors.newChachedThreadPool();(或任何其他方法) - 这样您的代码会更快。
  • 您可以使用线程池,其中每个池中的最大线程数保持不变。当这些线程加入时,可以将一个作业队列移交给池管理器,该管理器将管理一次有多少线程处于活动状态。
  • 不,线程 ID 溢出应该没有问题。如果您给线程名称,则更是如此。但是,我建议您使用其他方法自己实际创建 Thread 对象。执行器服务更适合您的需求。您需要的线程数等于按下按钮的次数,这看起来也很奇怪。你为什么需要那个?这可能会重复工作。

标签: java multithreading javafx


【解决方案1】:

创建线程非常昂贵。您应该改用某种线程池。 Executors 类提供了方便的方法来执行此操作。

所以例如你可以这样做:

private final ExecutorService exec = Executors.newCachedThreadPool();

然后

exec.submit(() -> doWork(someParam));

还有一些方法可以创建固定大小的线程池(Executors.newFixedThreadPool(n)),并且这些方法都是重载的,因此您可以在创建线程时定义如何创建线程。例如,如果你想要一个缓存线程池,但希望线程是守护线程(这样它们就不会阻止应用程序退出),你可以这样做

private final ExecutorService exec = Executors.newCachedThreadPool(runnable -> {
    Thread t = new Thread(runnable);
    t.setDaemon(true);
    return t ;
});

另请注意,在应用程序关闭时,您应该关闭线程池:

exec.shutdown();

据我所知,线程ID溢出不会造成问题;线程 id 是long,因此很难达到溢出,即使你这样做,它也会简单地换成一个很大的负数。但是,使用此处概述的线程池通常是更好的做法,这无论如何都会使这个问题变得毫无意义。

【讨论】:

  • 我写了以上作为对问题的评论,因为它没有回答问题“但是这是不好的做法吗?线程ID溢出时会出现问题吗?”
  • @ErwinBolwidt 好点。我添加了几句话,尽管与担心long 溢出相比,使用线程池有更好的理由。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-27
  • 2023-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多