-1

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.

halfer
  • 19,824
  • 17
  • 99
  • 186

1 Answers1

1

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:

  1. The difference between the Runnable and Callable interfaces in Java
  2. What are the advantages of using an ExecutorService?
  3. Executors.newCachedThreadPool() versus Executors.newFixedThreadPool()
Siddharth Kamaria
  • 2,448
  • 2
  • 17
  • 37