The cycle of learning never ends but starts often. In the case where threads are used It is an interesting cycle. One of the dangers of Java is that everybody can create and run threads. But the avoiding the pitfalls is needs a bit more experience. So lets see what we can do to avoid the known pitfalls.
The pitfalls:
Lets make a list of some pitfalls:
- Use the Runnable Interface
- Granuality of the synchronized parts
- Static code
- Scoping the objects in the threads.
- Order of executing the threads
- Setting members to Final
1. The Runnable Interface
This is important. Dont overload your class with unnecessary weight by letting it inherit from Thread.
Create a Thread and feed it with your object.
2. Granuality of the synchronized parts
You can ask yourself why is that important. You can say The more I have in my synchronized block the Less can go wrong. Or Why not the whole method that is easy and save anyway.
The consideration here is performance. Threads will wait on eachother when reaching a synchronized block. So the less you put in there the better it performs.
3. Static code:
Static code is something that gives a headache in multi threaded environments. It is on class level and not on an instance level. This means it is out of the scope of the ThreadManager and out of the scope of the garbage collector. My advice in most of the cases you setup an application, use it only when necessary and don't use it in a threaded envirnonment.
4. Scoping the objects in threads:
All the objects that are accesible in multiple threads should be scoped correctly. Public accessible member are also accesible over threads. This could give the case where you are using the synchronized block to prevent the threads to alter the values of the object while this is not necessarily.
5. Order of executing the threads
As you might create a number of threads, beware of the fact that in Java you cann't predict the order in which the threads will be executed. To test copy my example and instancate the ThreadObject in multiple threads with different names.
6. Setting members to Final
The final keyword in Java is a debatable one. As it does not occur in the compiled code it seems to be useless for many developers. My personal opinion about it is: It is not useless it is a programmers safety net. You do not need it to be compiled. It is like a frontdoor lock. So even in the matter of threads we can set members to final. This helps us to prevent other programmers to change the object. and leave them with nothing else then changing the values of the members of this object.
Example of a save thread:
public class NewThread {
/** this one is running in the main thread to execute the application.
* Dont use it as something that lives in one of your threads.
**/
public static void main(String[] args){
ThreadObject threadObject = new ThreadObject();
threadObject.setName("Pieter");
Thread thread = new Thread(threadObject);
thread.start();
}
public class ThreadObject implements Runnable {
private String name;
public String getName() {
/**
* HERE COULD HAVE BEEN SOME OTHER CODE
*/ synchronized (name) {
return name;
}
/**
* HERE COULD HAVE BEEN SOME OTHER CODE
*/
}
protected void setName(String name) {
/**
* HERE COULD HAVE BEEN SOME OTHER CODE
*/
synchronized (name) {
this.name = name;
}
/**
* HERE COULD HAVE BEEN SOME OTHER CODE
*/
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
System.out.println(getName());
}
Have fun!