Reputation:
Like ThreadPoolExecutor
class, I'm using private
background thread in my class (MyClass
).
However, once I start
my thread, anyone can invoke my thread's method like this:
Thread[] threads = new Thread[10];
Thread.currentThread().getThreadGroup().enumerate(threads);
threads[**index of my thread**].run();
and this kind of invocation breaks structure of MyClass
.
Of cource, I can use SecurityManager
to avoid this,
but I can't force user of MyClass
to run JVM with SecurityManager
installed.
So, if I don't want to break structure of MyClass
,
I have to write lengthy code like this:
@Override
public void run(){
if(.....) throw new UnsupportedOperationException("do not invoke run() directly");
}
@Override
public void setUncaughtExceptionHandler(.....){
throw new UnsupportedOperationException("cannot change handler");
}
........
Then, my question is "Who is the person responsible?"
Can I assume that no one invokes private thread's methods?
(imperfection caused by such invokation is negligible)
or
Do I have to prepare for illegal access?
(object have to be perfect in all cases)
and more generally,
Is there (official) programming standard about this kind of problem?
Thank you.
Upvotes: 0
Views: 108
Reputation: 27115
Here's a follow-up thought: If you are writing a library that other programmers will use, then instead of trying to hide your threads from your client, you should be doing the opposite: When you want to create a new thread, you should allow your client to create it for you.
Use a ThreadFactory
instance to create new threads.
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
ThreadFactory myThreadFactory = Executors.defaultThreadFactory();
public void setThreadFactory(ThreadFactory clientThreadFactory) {
myThreadFactory = clientThreadFactory;
}
void someMethodThatMakesAThread(...) {
Runnable r = new Runnable() {
@Override
public void run() {
...
}
};
Thread t = myThreadFactory.newThread(r);
t.start();
...
}
If the client chooses to call your setThreadFactory()
method, then your code will use the client's ThreadFactory
instance to make new threads. That gives the client a lot of power to debug the program, log thread creation events, control thread priorities, organize threads in ThreadGroups,... All of which makes your module more useful and more attractive to a programmer who wants to use it in a large program that has many other threads besides just yours.
On the other hand, if your client chooses not to call setThreadFactory()
then the default ThreadFactory
will basically just call new Thread(r)
for you.
Upvotes: 1
Reputation: 53694
Expanding on @jameslarge's comment, when you build code for others to use, you don't need to worry about "malicious" usage. You should build your API to be easy to use correctly and hard to use incorrectly (through appropriate documentation and reasonable use of visibility levels like public/protected/private). It is not your job, however, to worry about whether or not someone will purposely call the wrong methods at the wrong times. If they do that, then they "void the warranty". I'm not sure if you are new to Java or not, but regardless of what "protections" you put in, there are all manner of ways to subvert code and mess with it (using reflection, decompiling/modifying/recompiling, etc).
As a side note, the SecurityManager is not there to protect the code from the user (e.g. DRM and its ilk), but is instead designed to protect the user from the code. Hence it is not a valid way to protect your code from being "misused" by another developer.
UPDATE
Deprecation is a more complicated question. Think about the situation where someone has been using your code for a while. Ideally, they should be able to upgrade to new versions and not modify their code (assuming the new version is reasonably compatible with the old version). In this case, if a deprecated method "still works" but is no longer the "right way", you wouldn't want to start throwing exceptions in previously working code. If, however, you've given your users lots of warning, and now this method no longer works at all, then yes, you want to throw an exception. That said, if you are creating an entirely new API and happen to be exposing a class with a deprecated method that you never want your users to use, then throwing an exception in that case is also reasonable.
Upvotes: 1
Reputation: 3353
If I were you I would consider the following:
1) the thread is not meant to be re-runnable, it should be started (and run) only once.
2) in order to get your thread from Thread.currentThread().getThreadGroup().enumerate(threads);
you thread has to be running already.
3) Adding simple check if (isRunning()) { throw ... }
at the start of your run()
method should solve you problems
Upvotes: 0