File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Threads and Synchronization and the fly likes Which type of implementation, extends Thread or implements Runnable. ? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Which type of implementation, extends Thread or implements Runnable. ?" Watch "Which type of implementation, extends Thread or implements Runnable. ?" New topic
Author

Which type of implementation, extends Thread or implements Runnable. ?

Fred Hamilton
Ranch Hand

Joined: May 13, 2009
Posts: 679
I can't remember if I asked this question before, excuse me if I have it's been lost in the shuffle.

Anyways, my experience with thread programming is limited, and I am trying to decide how best to implement threads into my java chess program. The program is pretty good as far as it goes, but right now it is just a single threaded app. This leads to the following problem.

When I make a move, a command is issued to repaint the board (a JPanel). At the same time, the chess engine (computer brain) starts churning, to calculate the next move. As a result, CPU is hogged, and the board doesn't complete the repaint until the computer makes it's own move.

I figure one solution to this is to have the "chess engine" run in its own thread, with appropriate priority. One other advantage of this is that it will allow the chess engine to think even when it is not it's turn.

I understand there are two ways to do implement a thread, have my engine class extend Thread or implement Runnable. It is my undersatnding that the only real difference between the two is that implementing runnable is preferrable because of flexibility, it won't prevent you from extending another class if you need to. In any event, I don't really have any concerns with how to do either at this point.

Anyways, this is just a hobby project, and for my purposes I prefer to have my engine class extend thread, if practical. I don't think I will need to extend any other class. Future development for this class will include a fairly sophisticated hash table, and also a sophisticated recursive algorithm. As far as I can see, neither of these will require that I extend another class, but on this point I am not 100% certain.

Anyways, I just wanted to bounce these thoughts off of someone, in case there are any major flaws in my thinking that will require major rework down the road, which naturally I want to avoid.

regards.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

I always implement Runnable, out of theory (I am not changing or adding to how Thread, in general, functions. I am just making a task to run in a Thread), but also in practicality.

1) As you said, Runnable is more flexible. You can extend a different class, etc... You can use it in the ExecutorServices if your app begins to grow enough to need more than 1 background thread, for example. A Thread is a Runnable, so you can use it the same places, but it is so much heavier, why carry the extra weight around?

2) When you begin to work in a multi-threaded environment, you will want to synchronize calls. When you implement a Runnable, synchronizing on the Runnable object is straight-forward - just like synching on any other Object. There are no surprises when you wait() or notify() on the Runnable instance. That isn't so on a Thread. Thread will have internal and undocumented notify()s which makes using it reliably for synchronization is tough to do.

In the end, using the interface ends up being cleaner design. It doesn't cost much - 1 extra Object, which is what makes it a good choice except in those special-case scenarios where you really want to change Thread behavior.


As far as I can see, neither of these will require that I extend another class, but on this point I am not 100% certain.


And to this point, if you aren't certain, play conservative and leave that extension path open.


Anyways, I just wanted to bounce these thoughts off of someone, in case there are any major flaws in my thinking that will require major rework down the road, which naturally I want to avoid.

It usually doesn't require major rework unless you do need to extend something later on - Thread implements Runnable, and so can be used wherever Runnable is. The question I have is, what does making it a Thread give you that making it a Runnable doesn't? If it is about easier caller code:

versus


Then I would suggest wrapping the 'start()' into the runnable:


Steve
Fred Hamilton
Ranch Hand

Joined: May 13, 2009
Posts: 679
OK, thanks Steve, my main reason for preferring to extend class was just that it seemed easier, more intuitive, but from what you have described, implementing runnable doesn't sound that onerous. Probably what I'm gonna do is just write a simple prototype to put some of your ideas into practice, I'm sure I'll understand them better then. If I have any questions in a day or two, I'll come back to this thread.

I do have one question though. In comment 1) of your post, what did you mean by

"... it is so much heavier, why carry the extra weight around?"

thanks.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Fred Hamilton wrote:OK, thanks Steve, my main reason for preferring to extend class was just that it seemed easier, more intuitive, but from what you have described, implementing runnable doesn't sound that onerous. Probably what I'm gonna do is just write a simple prototype to put some of your ideas into practice, I'm sure I'll understand them better then. If I have any questions in a day or two, I'll come back to this thread.

I do have one question though. In comment 1) of your post, what did you mean by

"... it is so much heavier, why carry the extra weight around?"

thanks.


Thread has a bunch of internals that it needs to function properly - references to ThreadGroup, native code links for running the thread, counters, locks, things like that. What I was saying in 1) is that Thread is a Runnable, so you can use it in ExecutorServices, and other places that requires a Runnable. But if all you need is a Runnable you should avoid carrying around all that extra internal baggage that Thread has - all those member variables and data.
Fred Hamilton
Ranch Hand

Joined: May 13, 2009
Posts: 679
Well, just to close this particular chapter, this turned out to be much easier than I thought.

A simplified explanation...

In my main GUI class, I have a mouseReleased method which gets called when I place a piece on a particular square. A number of tasks get performed, then we have the following sequence...

board.repaint();
comp.makeMove(); // comp is the engine object

So the problem was that makeMove() would hog the CPU before the board could finish the repaint. So...

1. have my main GUI class implement Runnable.
2. my run() method consists of a single line comp.makeMove().

in my mouseReleased method, comp.makeMove(); gets replaced by (new Thread(this)).start();

voila! anyways, further R&D may suggest something different, I don't know, but at least now I get prompt redraws of my chessboard.

Thanks again Steve.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

This is the correct strategy, but you will probably be better of not using the GUI as a runnable. What happens when you have another button that needs a long task? It is better to separate the concerns. One strategy would be to make your makeMove method control the threading behavior:


Just because my mind is wandering, you could also make things a bit more efficient by using a single thread that just takes commands as when to work:

I guess this is where things get a bit more complicated, though, because you would have to remember to shutdown the aiThread when the program comes to an end.

Just to throw another strategy out there which may be nice would be to store the Runnables which are used to execute methods as final members of the comp class...


Fred Hamilton
Ranch Hand

Joined: May 13, 2009
Posts: 679
Duly noted, and food for thought. I was thinking that I am limiting myself by this particular design, but chess is hardly a multitasking application anyway. As long as the computer's thinking does not interfere with my ability to move a piece, then there is no problem. But for me it's not just about building a better mousetrap, it's also a fun vehicle to learn different programming techniques, so all methods have value.

Just a comment specifically about chess engines. As I see it, a properly designed engine does one thing only, crunch and evaluate variations, that is it's purpose. Any other tasks are done in a different class. I see no value in dividing up that job, it may as well be linear, all the work still needs to be done. I don't see that an engine needs to flag any other tasks, except to tell the main application that it has a move to make. Perhaps in that sense having an engine class extend thread is not such a bad idea after all.

Anyways, I'll file all this for future reference, thanks for the insights.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Which type of implementation, extends Thread or implements Runnable. ?