Ok, I am going to admit to be new to threading in Java, I have been doing alot of reading about java.util.concurrent and I have a few questions that I was hoping a real person could answer.
First I have created ThreadPoolExecutor and BlockQueue to help run my Runnable/Callable methods. To keep things simple with my limited knownledge I have limited all activity to read only, no Objects passed into the Runnable is modified, and the information created is a pull from a database that is used by the application to populate GUI tables, any information in the database can be changed either before or after it is recieved, doesn’t matter for display purposes.
What I am curious about is if what I have done is thread safe. I have extended ThreadPoolExecutor so I can Override the afterExecute method to execute a method within the Runnable after it has finished its work in the thread. From what I have read it seems that this operation is done in the main thread and would be considered thread safe.
Also continueing with this idea, if I write another method that is also within this Runnable/Callable class and use it directly without the use of run (or ThreadPoolExecutor.execute()) that it would also run on the main thread and be safe. Question Two: If I use this method from the run() method of the Runnable class is it run on the thread? (I assume it is, and ask for confirmation) AND If I run this method directly would it be run on the main thread?
The reason is because I wish to keep everything that has to do with a query/update/insert within one class but keep updates to the database in the main thread.
A bit of code to help explain:
The extended ThreadPoolExecutor:
public class DatabaseThreadPoolExecutor extends ThreadPoolExecutor {
public DatabaseThreadPool(int corePoolSize, int maximumPoolSize, long keepAlive, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(//pass info to super)
}
protected void afterExecute(Runnable runnable, Throwable throwable) {
if(runnable instanceof someRunnable) {
((SomeRunnable) runnable).afterExecution();
}
}
}
The Runnable class:
public class someRunable implements Runable {
public someRunnable() {
// used code withing thread
}
public doAfterExecute() {
// run by ThreadPoolExecutor .afterExecute()
}
public doSomething() {
// Run by someRunnable in thread
// Also run directly by some other class
}
}
Some other class that calls doSomething():
public class someOtherClass {
public SomeOtherClass(Runnable someRunnable) {
someRunable.doSomething();
}
}
There is no way to say that such a high level description is ‘threadsafe’ without seeing all the code. For all we know you’re using an architecture where ‘reads’ are a blocking operation and it’s going to deadlock on you!
Generally one can describe a resource, or a class, as ‘threadsafe’ meaning that it will not exhibit unpredictable behaviour when used by multiple threads. But a given resource being ‘threadsafe’ is not a certification that you won’t cause any bugs when you try to do things in parallel that wouldn’t have happened if it’d all been done on one thread. Just that the behaviour is predictable (for any given set of timings, which of course are not themselves predictable).
Being ‘threadsafe’ is also not an indication that something is actually suited to highly concurrent usage. A fully synchronized ArrayList is ‘threadsafe’ but you certainly wouldn’t want to write a program that shared it among lots of threads that constantly use it!
Will try to answer your actual questions though!:
This seems like a demonstrably false statement. If your runnable does anything at all, the stuff you’re reading must be going somewhere. That somewhere must be something that the runnable has a reference to. How the resource that you’re pushing the read results into responds to concurrent access is what you need to analyze. That’s where the potential hazards lie.
No, afterExecute() will be called in the same pool thread that invoked the run() method on your runnable. Not in the thread that submitted the Runnable. “This method is invoked by the thread that executed the task“
Yes it will run in the thread where you call the method from, not in a pool thread. “Be Safe” is something we cannot begin to tell from just an architecture description ( and an agreed upon definition of safe) :).
Yes, anything you call inside the run() method will be executed by the pool thread that picks up your task.