19. april 2004 - 14:14Der er
15 kommentarer og 3 løsninger
Threads, which way is the best?
Hello!
I would like to get some comment around this code about Threads.
I use to build apps with Threads like pattern Thread1. I could also build it like code ex Thread2, but I'm pretty sure that it is prefferable to do it like Thread1 but I can't remeber why! So if any one could help me with some comment which pattern is the best.
Best regards Fredrik
BTW please give answers so I can avard all of you!
//Pattern 1
import java.awt.*; import java.applet.*;
public class Thread1 implements Runnable { Thread thread; boolean run; int state = 0;
public static void main(String[] args) { new Thread1(); }
public Thread1() { start(); }
public void run() { while(run) { try { switch(state) { case 0: thread.sleep(500); state = 1; break; case 1: doSomeStuff(); state = 0; break; } } catch (InterruptedException e) { e.printStackTrace(); } } }
public void start() { run = true; if(thread == null) { thread = new Thread(this); } thread.start(); }
public void stop() { run = false; thread = null; }
If we look at the two possibilities that arne_v is mentioning: extends Thread og implements Runnable, the last one i would say is always the best.
There is no difference in the way the Thread works, but if you extends Thread, you WILL have to start the thread in the constructor. If you do not do that, you might not be sure that the thread is started ever started.
If you instantiates a class extending Thread without starting the thread, you will have an unstarted thread/process-instance allocated in the OS's kernel. Even if you drop all references to the class extending Thread, this class-instance will never be garbage collected, because the unstarted thread is holding a reference. This will both result in an ugly memory-leak AND the kernel having one more thread/proces that never gets started nor removed.
If you are always 100 percent sure, that the thread is started when extending Thread, there is really no difference besides what arne_v mentions, that implementing Runnable is a more flexible solution, becuse you have te possibility to extend other classes instead.
Just to add to the discussion: In my opinion you should never let the thread class itself call start, and definitively not in its constructor since this can cause race conditions.
You don't always know who will use and derive from your classes in the future which can cause problems as the small fictive example below illustrates:
import java.awt.*; import java.applet.*;
public class Thread1 extends Thread {
public Thread1() { start(); }
public void run() {} }
import java.awt.*; import java.applet.*;
public class Thread2 extends Thread1 { boolean run= true; int state = 0; int[] someResource;
public static void main(String[] args) { new Thread2(); }
public Thread2() { super(); //simulate some lenghty initialization try { sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } //something is initialized after start() is actually called someResource = new int[1000]; for(int i = 0;i < 1000;i++) { someResource[i] = i; } }
public void run() { while(run) { try { doSomeStuff();
Conrad >> I suppose you would rather prefer a memory-leak and total machine crash, than starting the Thread in the derived class? My opinion is still that the best way is to implement Runnable - but having unstarted threads in kernel woithout the possibility to remove them without restarting the JVM is very serious. I have seen an example were a server chrashed daily because of this bug. In rare cases the threads did not get started, and when the server-load increased, the server simply chrashed because of full memory, used by the kernel.
That "You don't always know who will use and derive from your classes in the future" is actually I think, the primary reason to start the thread in the constructor of the derived class. You cannot be sure, that the thread is always started, which results in a heavy memory-leak - this is never acceptable.
I don't have any experience with server programming and problems like the one you encountered, so I am really not an expert on that area, and I was thinking more in application development.
I do however find it hard to see why it should be a problem to instantiate the thread and the call start() like below ? (of cause you can't prevent that people forget)
Thread1 t = new Thread1(); t.start();
but maybe you can tell me when this can be a problem ?
To support my case I will mention that javas own implementation of threads does not start the thread in the constructor :)
Whether to use extends Thread or implements Runnable and whether to start the thread in the constructor or not must be two independent questions - all four combinations are valid
2)
I usually use extends Thread and call start after having created the object
It is always interesting to get experts opinions, and for me everything seems more clearer.
Since Conrad took part of the disscusion I think he salso should take part of the points. So if you see this conrad, just throw in a Svar so I could give you your part of the points.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.