英文:
Java Multithreading: Too many options
问题
我一直在研究数独求解器/生成器,以便开始使用Java。求解和生成是在后台使用SwingWorker
进行的。现在,我想要进行批量生成,即程序会生成许多数独(数十个或数百个)。因此,我希望尽可能多地利用计算机上的线程,而不仅仅是一个线程。然后,我将需要与可用线程数量相同的SwingWorker
实例。但这会引发问题,因为SwingWorker
一次只能有10个实例。因此,我想要另一个解决方案来解决这个问题。
我已经研究了多线程选项,似乎有太多了:Thread、Runnable、Callable、ExecutorService、SwingWorker
等等。我想知道,哪个最适合我的目的。
我也读过实现Runnable
要比扩展Thread
好。
我需要传递数据,然后在另一个线程上开始执行,当它完成时,我希望通知感兴趣的监听器,然后它们可以请求数据。我在考虑可以创建一个Runnable
,使用volatile
变量,我还可以取消执行,并在执行结束时使用SwingUtilities.invokeLater()
通知监听器。我还希望根据需要多次重新启动这个循环。
SwingWorker
不行,因为它在实例数量上受限,而且不能重新启动。
数独算法我已经做得很好了,我只需要将生成算法封装到某个东西中,以使其支持多线程。
英文:
I have been working on sudoku solver/generator to get started with Java. The solving and generation is done in background using SwingWorker
. Now I want to have batch generation, where the program would generate many sudokus (tens or hundreds). Therefore, I want to use as many threads on a computer as possible, not just one. I would then need as many SwingWorker
instances as there are threads available. Which will cause problems since SwingWorker
is limited to 10 instances at a time. Therefore I want another solution to this problem.
I have looked into multithreading options and there seems to be too many of them: Thread, Runnable, Callable, ExecutorService, SwingWorker,...
. I want to know, which one is best suited for my purpose.
I have also read about implementing a Runnable
is better than extending a Thread
.
I need to pass data, then start the execution on another thread, and when it finishes, I want to notify interested listeners, that can then request data. I was thinking I could create a Runnable
, using a volatile
variable I could also cancel the execution, and at the end of the execution, notify listeners using SwingUtilities.invokeLater()
. I also want to restart this cycle as many times as needed.
SwingWorker
is out because it is limited in number of instances and cannot be restarted.
I have the sudoku algorithms working fine, I just need to wrap the generation algorithms in something to make it support multithreading.
答案1
得分: 1
以下是翻译好的内容:
线程(Thread):一个代表线程的类,同时实现了Runnable
接口。出于多重继承的原因之一,最好实现Runnable
,因为Java不允许类的多重继承,但允许接口的多重继承。
可运行(Runnable):一个函数式接口,您在其中指定在线程上要执行的操作,使用run()
方法。确保将可运行对象作为new Thread(runnable).start()
来运行。如果不需要返回值,这是一个很好的选择。
可调用(Callable):类似于可运行,但您可以获得返回值。同样,它是一个具有call()
方法的函数式接口,该方法返回类型为T
的值。您将获得一个Future<T>
对象,当您调用future.get()
(这是一个阻塞调用)时,它会保存一个获取值的承诺。
ExecutorService:生成线程的成本很高,如果您反复执行此操作,考虑使用此功能并重用线程。在Executors类中有一些值得检查的模板线程池,如newSingleThreadExecutor()
、newFixedThreadPool(threadCount)
和newCachedThreadPool()
(这是无界的!)。
一些值得查看的好的Stack Overflow帖子:
- Java中Runnable和Callable接口的区别
- 使用ExecutorService的优点是什么?
- Executors.newCachedThreadPool()与Executors.newFixedThreadPool()之间的区别
英文:
Here's a cheat sheet which I like to use.
Thread: A class which embodies a thread, which also happens to implement Runnable
. It's better to implement Runnable
for several reasons, one of them being Java disallows multiple inheritance for classes but does allow it for interfaces.
Runnable: A functional interface where you specify what to do on your thread in a run()
method. Make sure you run your runnable as new Thread(runnable).start()
. Good choice if you don't need a return value.
Callable: Similar to Runnable but you can get a return value. Again, a functional interface with a call()
method which returns type T
. You get a Future<T>
object which holds a promise to get a value when you do future.get()
(which is a blocking call)
ExecutorService: Spawning threads is expensive, if you're doing it over and over, consider using this and reusing the threads. There are a few template thread pools worth checking out in the Executors class like newSingleThreadExecutor()
, newFixedThreadPool(threadCount)
and newCachedThreadPool()
(this is unbounded!).
Some good SO posts worth checking out:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论