I’m writing a Java program involving a multithreaded worker pool of Processes. Each instance of the class Process needs to be able to spawn a single additional thread to do some work. But the thread should by spawned by the instance itself and nobody else. Unfortunately Runnable.run is ‘public’ so I cannot really enforce this without doing some trick.
Here is the trick I plan to use:
- Implement
RunnableinProcess - Write this into the implementation:
Code:
class Process implements Runnable {
private boolean threadkey = false;
public void run() {
synchronized(threadkey) {
// is someone wrongly calling 'run'?
if(!threadkey)
return;
/* switch off threadkey to make sure
it cannot be called meaningfully again */
threadkey = false;
}
/* continue processing
*
*/
return;
}
Of course, now all I will need to do when I want to run legitimately is to switch on ‘threadkey’ (which is private) before making the call.
Elegant? Or not? Or is there a better way? Or should I just not bother with enforcing this and write a neat little comment explaining NOT to call ‘run’?
Do people even call ‘run’ from within the class that needs to do the ‘running’?
While you are correct that the
runmethod of aRunnableis public, one thing you can do to prevent other people from calling it is to make your entireRunnableimplementation a package-private class or a private inner class. This way, while it may have apublicrunmethod, code other than your custom class cannot instantiate theRunnableobject. If you also have your class not hand back references to it, then clients won’t have access to theRunnable, and so they can’t invokerun. That is, don’t have yourProcessclass implementRunnable; instead, make another class that actually implementsRunnable, then makeProcessthe only class that can access it.This approach is more elegant than what you have proposed because it prevents other code from calling
runat compile-time rather than at runtime. In particular, if any code tries to call yourrunmethod described above, it will compile just fine, and will fail at runtime. The problem is that the code will compile but can never work correctly. Making theRunnableinaccessible means that if someone does try to run it, they’ll get a compile-time error and will have to rethink their design. In other words, the compiler will detect the error before it even happens.In general, if you ever find yourself wanting to prevent random code from calling methods of a class that have to be public because they’re declared in an interface, consider changing the access specifier for the entire class so that clients can’t reference it.