I have thread application which process heavy task, i would like to trigger forcibly stop thread upon external flag information. I have tried following design,
public class HeavyTaskThread implements Runnable
{
private boolean forceStop;
public void run()
{
..
..
..
..
}
}
Another fact is i do not have control of logic flow implemented into method run(); which simply call some third-party program. I was trying with light inner thread class and calling method interrupt() on parent thread, but this does not work.
Please suggest any pattern....
The recommended way to handle the activity of third-party code that you have no control over is to launch it as a different process instead. Then simply kill the process when you need to forcibly stop the code. It's much more clean and safe than killing a thread, since it does not affect the parent process and the OS will take care of the cleanup duty.
If the third party program doesn't respond to an interrupt or setting a condition, an icky option is to try to kill it by nulling a key variable, closing a socket or file, etc. And hoping that it terminates gracefully. Like I said, icky but sometimes you gotta do what you gotta do...
If whatever third-party program you call in run() never returns, you're out of luck. If it returns periodically, you can make it loop, checking against a volatile forceStop boolean and exiting the loop when it's true:
private volatile boolean forceStop;
public void run()
{
while(!forceStop) {
..
..
}
}
While I'd vote for Tudor's answer, in the extreme and if you're desperate:
Option A - Reconstruct problem code.
Use your favorite java decompiler & re-create problem class.
Add check for Thread.currentThread().isInterrupted() into run.
Compile, place your modified class before original library in the classpath.
If the original jar was signed you may have to eliminate related signature artifacts.
Option B - Aspect J
Examine source for the run method, use your favorite java decompiler if necessary.
Identify a some reasonable point in the inner loop for stepping in and stopping.
Examine exception handling in code. Any loop-holes?
Inject code: throw exceptions, catch exceptions, etc. as needed to back out and return from run.
Here is final analysis...for killing thread.
Using Thread to control the execution of Program B. But then stopping a process means via a thread is not allowed as the related methods are deprecated (stop/suspend etc.,)
Using ThreadGroup ( to have only one thread as its member) and calling 'destroy' on the group. But it again falls on the same track as every thread should be stopped before the destroy operation is attempeted.
Process/ProcessBuilder via Runtime seems to be the better way to obtain a process reference and call destroy(), waitFor() etc. as user #Tudor mentioned.
Here is exact outlined code i have tried and it fails to kill, commented line while(isValid()) represents my another java program invoke.
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
class TaskWorker implements Callable {
private final int number;
public TaskWorker(int number) {
this.number = number;
}
public Boolean call() throws InterruptedException {
while (!Thread.currentThread().isInterrupted()) {
myBusyFunction();
}
return true;
}
private boolean isValid() {
return true;
}
private void myBusyFunction() {
//while (isValid()) {
System.out.println(number + ">....Working.....");
//}
}
}
public class Test {
public static void main(final String[] args) {
CompletionService cs = new ExecutorCompletionService(Executors.newFixedThreadPool(1));
Collection tasks = new ArrayList(10);
tasks.add(new TaskWorker(1));
List> futures = new ArrayList>(tasks.size());
try {
for (Callable task : tasks) {
futures.add(cs.submit(task));
}
//----
for (int t = 0; t result = cs.poll(10, TimeUnit.SECONDS);
if (result == null) {
System.out.println(new Date() + ":Worker Timedout:");
//So lets cancel the first futures we find that havent completed
for (Future future : futures) {
System.out.println("Checking future");
if (future.isDone()) {
continue;
} else {
future.cancel(true);
System.out.println("Cancelled");
break;
}
}
continue;
} else {
try {
if (result.isDone() && !result.isCancelled() && result.get()) {
System.out.println(new Date() + ":Worker Completed:");
} else if (result.isDone() && !result.isCancelled() && !result.get()) {
System.out.println(new Date() + ":Worker Failed");
}
} catch (ExecutionException ee) {
ee.printStackTrace(System.out);
}
}
}
} catch (InterruptedException ie) {
} finally {
//Cancel by interrupting any existing tasks currently running in Executor Service
for (Future f : futures) {
f.cancel(true);
}
}
System.out.println(new Date() + ":Done");
}
}
Related
I have a method name someTask that I have to invoke 100 times and I am using asynchronous coding as below.
for (int i = 0; i < 100; i++) {
futures.add(CompletableFuture.supplyAsync(
() -> { someTask(); },
myexecutor
));
}
If an exception occurs on any thread while executing someTask() I want to interrupt all the current threads and also stop future threads from executing. What is the best way to handle this?
Update:
I am using ThreadPoolTaskExecutor.
Since you don't seem to be using the CompletableFuture specific methods, you could use an ExecutorService directly:
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
try {
someTask();
} catch (InterruptedException e) {
//interrupted, just exit
Thread.currentThread().interrupt();
} catch (Exception e) {
//some other exception: cancel everything
executorService.shutdownNow();
}
});
}
shutdownNow will interrupt all the already submitted tasks and the executor will refuse new task submission with a RejectedExecutionException.
The main drawback with this approach is that the ExecutorService cannot be reused, although you can of course create a new one. If that's a problem you will need another way.
Note that for this to work efficiently someTask() needs to regularly check the interrupted status of the thread and exit on interruption, or use interruptible methods. For example if someTask is a loop running some calculations and you never check the Thread interrupted status, the loop will run entirely and will not be stopped.
There are many ways to do that and all depend on the exact use case. But all ways (I'd say) have one thing in common: you'll have to end the tasks in a controlled manner. You can't just "instant-terminate" the execution of a task because this could lead to inconsitent data and other problems. This is usually done by checking some flag, e.g. Thread.isInterrupted(), and ending the execution manually if it's signaling that the execution shall cancel. You can use a custom flag as well, which I'll show:
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
class Main {
static final ExecutorService executor = Executors.newCachedThreadPool();
// just dummy stuff to simulate calculation
static void someStuff(AtomicBoolean cancel) {
if (cancel.get()) {
System.out.println("interrupted");
return;
}
System.out.println("doing stuff");
for (int i = 0; i < 100_000_000; i++) {
Math.sqrt(Math.log(i));
}
}
static void someTask(AtomicBoolean cancel) {
someStuff(cancel);
someStuff(cancel);
someStuff(cancel);
}
public static void main(String[] args) {
final Set<CompletableFuture<?>> futures = new HashSet<>();
final AtomicBoolean cancel = new AtomicBoolean();
for (int i = 0; i < 10; i++) {
futures.add(CompletableFuture.supplyAsync(
() -> {someTask(cancel); return null;}, executor
));
}
futures.add(CompletableFuture.supplyAsync(() -> {
try {
throw new RuntimeException("dummy exception");
}
catch (RuntimeException re) {
cancel.set(true);
}
return null;
}));
futures.forEach(cf -> cf.join());
executor.shutdownNow();
}
}
Notice that the final task is throwing an exception and handles it by setting the flag cancel to true. All the other tasks will see that by checking it periodically. They will cancel their execution if the flag signals it. If you comment out the exception-throwing task, all tasks will just finish normally.
Note that this approach is independent of the executor used.
Consider this code:
class Solver {
private boolean abort = false;
public void solve(List<Case> cases) {
while(!abort) {
for(Case c : cases)
compute(c); // method that take too long to finish
}
}
// a bunch of methods
public void abort() {
abort = true;
}
}
// in another class
Solver solver = new Solver();
solver.solve(cases);
public void onSolveAborted() {
solver.abort();
}
How can I change this solution so I can abort the solve function instantly. I know I can implements the Runnable interface in Solver class so I can stop the thread. This will introduce many changes in our code and I don't know if the framework we are using allow creating threads.
This will not be possible without the use of threads. Something has to set abort() before the running thread will stop. Take a look at this example:
class Solver implements Runnable {
private List<Case> cases;
public Solver(List<Case> cases) {
this.cases = cases;
}
private void compute(Case c) {
try {
// Do some computation here
} finally {
// Sound the horns! Abandon ship!
}
}
public void solve(List<Object> cases) {
for (Case c : cases) {
try {
compute(c); // method that take too long to finish
} catch (InterruptedException e) {
// Hmm, maybe I should take the hint...
break;
}
}
}
public void run() {
solve(cases);
}
public static void main(String args[]) {
List<Case> cases = new ArrayList<Case>();
// Populate cases
Thread t = new Thread(new Solver(cases));
t.run();
do {
// Wait 30 seconds
t.join(30 * 1000);
// Not done yet? Lets drop a hint..
if(t.isAlive()) {
t.interrupt();
}
} while (t.isAlive());
}
}
Very simply, it launches solve in a thread. The main thread waits up to 30 seconds then interrupts solve method. The solve method catches the interruption and gracefully exits the computation. Unlike your solution using boolean abort, this launches an InterruptedException from anywhere in your thead code (and you should deal with the exception accordingly!) allowing you to halt execution at any time.
If you want more control, you can add the try.. catch inside compute so you can have a finally clause to close any opened files or whatnot. Perhaps better still, have a try.. finally in compute to deal with closing things in a "nice" way and the try.. catch (InterruptedException) in the solve method to handle what happens in the case of interruption (in short, cleanup logic and interruption logic don't have to be in the same method).
Do somthing like this
Let say, you have 100 cases, 10 has been solved and you want to abort remaing 90.
In your code, you are solving all the cases in one iteration, after that while loop check for abort.
public void solve(List<Case> cases) {
Iterator<Case> iterator = cases.iterator();
while (iterator.hasNext() && !abort) {
Case c=iterator.iterator.next();
compute(c);
}
}
Change your class to Runnable and use ExecutorService to run it. Then you can just use methods "shutDown()" or "shutDownNow()" methods. This is cleaner and less intrusive then what you suggested in your own question. Plus killing thread manually is a REALLY BAD idea. At some point in JDK itself in thread method "kill()" was killed as there is no clean way to do so properly
How do you kill a java.lang.Thread in Java?
See this thread by Sun on why they deprecated Thread.stop(). It goes into detail about why this was a bad method and what should be done to safely stop threads in general.
The way they recommend is to use a shared variable as a flag which asks the background thread to stop. This variable can then be set by a different object requesting the thread terminate.
Generally you don't..
You ask it to interrupt whatever it is doing using Thread.interrupt() (javadoc link)
A good explanation of why is in the javadoc here (java technote link)
In Java threads are not killed, but the stopping of a thread is done in a cooperative way. The thread is asked to terminate and the thread can then shutdown gracefully.
Often a volatile boolean field is used which the thread periodically checks and terminates when it is set to the corresponding value.
I would not use a boolean to check whether the thread should terminate. If you use volatile as a field modifier, this will work reliable, but if your code becomes more complex, for instead uses other blocking methods inside the while loop, it might happen, that your code will not terminate at all or at least takes longer as you might want.
Certain blocking library methods support interruption.
Every thread has already a boolean flag interrupted status and you should make use of it. It can be implemented like this:
public void run() {
try {
while (!interrupted()) {
// ...
}
} catch (InterruptedException consumed)
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }
Source code adapted from Java Concurrency in Practice. Since the cancel() method is public you can let another thread invoke this method as you wanted.
One way is by setting a class variable and using it as a sentinel.
Class Outer {
public static volatile flag = true;
Outer() {
new Test().start();
}
class Test extends Thread {
public void run() {
while (Outer.flag) {
//do stuff here
}
}
}
}
Set an external class variable, i.e. flag = true in the above example. Set it to false to 'kill' the thread.
I want to add several observations, based on the comments that have accumulated.
Thread.stop() will stop a thread if the security manager allows it.
Thread.stop() is dangerous. Having said that, if you are working in a JEE environment and you have no control over the code being called, it may be necessary; see Why is Thread.stop deprecated?
You should never stop stop a container worker thread. If you want to run code that tends to hang, (carefully) start a new daemon thread and monitor it, killing if necessary.
stop() creates a new ThreadDeathError error on the calling thread and then throws that error on the target thread. Therefore, the stack trace is generally worthless.
In JRE 6, stop() checks with the security manager and then calls stop1() that calls stop0(). stop0() is native code.
As of Java 13 Thread.stop() has not been removed (yet), but Thread.stop(Throwable) was removed in Java 11. (mailing list, JDK-8204243)
There is a way how you can do it. But if you had to use it, either you are a bad programmer or you are using a code written by bad programmers. So, you should think about stopping being a bad programmer or stopping using this bad code.
This solution is only for situations when THERE IS NO OTHER WAY.
Thread f = <A thread to be stopped>
Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} );
m.setAccessible( true );
m.invoke( f , new ThreadDeath() );
I'd vote for Thread.stop().
As for instance you have a long lasting operation (like a network request).
Supposedly you are waiting for a response, but it can take time and the user navigated to other UI.
This waiting thread is now a) useless b) potential problem because when he will get result, it's completely useless and he will trigger callbacks that can lead to number of errors.
All of that and he can do response processing that could be CPU intense. And you, as a developer, cannot even stop it, because you can't throw if (Thread.currentThread().isInterrupted()) lines in all code.
So the inability to forcefully stop a thread it weird.
The question is rather vague. If you meant “how do I write a program so that a thread stops running when I want it to”, then various other responses should be helpful. But if you meant “I have an emergency with a server I cannot restart right now and I just need a particular thread to die, come what may”, then you need an intervention tool to match monitoring tools like jstack.
For this purpose I created jkillthread. See its instructions for usage.
There is of course the case where you are running some kind of not-completely-trusted code. (I personally have this by allowing uploaded scripts to execute in my Java environment. Yes, there are security alarm bell ringing everywhere, but it's part of the application.) In this unfortunate instance you first of all are merely being hopeful by asking script writers to respect some kind of boolean run/don't-run signal. Your only decent fail safe is to call the stop method on the thread if, say, it runs longer than some timeout.
But, this is just "decent", and not absolute, because the code could catch the ThreadDeath error (or whatever exception you explicitly throw), and not rethrow it like a gentlemanly thread is supposed to do. So, the bottom line is AFAIA there is no absolute fail safe.
'Killing a thread' is not the right phrase to use. Here is one way we can implement graceful completion/exit of the thread on will:
Runnable which I used:
class TaskThread implements Runnable {
boolean shouldStop;
public TaskThread(boolean shouldStop) {
this.shouldStop = shouldStop;
}
#Override
public void run() {
System.out.println("Thread has started");
while (!shouldStop) {
// do something
}
System.out.println("Thread has ended");
}
public void stop() {
shouldStop = true;
}
}
The triggering class:
public class ThreadStop {
public static void main(String[] args) {
System.out.println("Start");
// Start the thread
TaskThread task = new TaskThread(false);
Thread t = new Thread(task);
t.start();
// Stop the thread
task.stop();
System.out.println("End");
}
}
There is no way to gracefully kill a thread.
You can try to interrupt the thread, one commons strategy is to use a poison pill to message the thread to stop itself
public class CancelSupport {
public static class CommandExecutor implements Runnable {
private BlockingQueue<String> queue;
public static final String POISON_PILL = “stopnow”;
public CommandExecutor(BlockingQueue<String> queue) {
this.queue=queue;
}
#Override
public void run() {
boolean stop=false;
while(!stop) {
try {
String command=queue.take();
if(POISON_PILL.equals(command)) {
stop=true;
} else {
// do command
System.out.println(command);
}
} catch (InterruptedException e) {
stop=true;
}
}
System.out.println(“Stopping execution”);
}
}
}
BlockingQueue<String> queue=new LinkedBlockingQueue<String>();
Thread t=new Thread(new CommandExecutor(queue));
queue.put(“hello”);
queue.put(“world”);
t.start();
Thread.sleep(1000);
queue.put(“stopnow”);
http://anandsekar.github.io/cancel-support-for-threads/
Generally you don't kill, stop, or interrupt a thread (or check wheter it is interrupted()), but let it terminate naturally.
It is simple. You can use any loop together with (volatile) boolean variable inside run() method to control thread's activity. You can also return from active thread to the main thread to stop it.
This way you gracefully kill a thread :) .
Attempts of abrupt thread termination are well-known bad programming practice and evidence of poor application design. All threads in the multithreaded application explicitly and implicitly share the same process state and forced to cooperate with each other to keep it consistent, otherwise your application will be prone to the bugs which will be really hard to diagnose. So, it is a responsibility of developer to provide an assurance of such consistency via careful and clear application design.
There are two main right solutions for the controlled threads terminations:
Use of the shared volatile flag
Use of the pair of Thread.interrupt() and Thread.interrupted() methods.
Good and detailed explanation of the issues related to the abrupt threads termination as well as examples of wrong and right solutions for the controlled threads termination can be found here:
https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads
Here are a couple of good reads on the subject:
What Do You Do With InterruptedException?
Shutting down threads cleanly
I didn't get the interrupt to work in Android, so I used this method, works perfectly:
boolean shouldCheckUpdates = true;
private void startupCheckForUpdatesEveryFewSeconds() {
Thread t = new Thread(new CheckUpdates());
t.start();
}
private class CheckUpdates implements Runnable{
public void run() {
while (shouldCheckUpdates){
//Thread sleep 3 seconds
System.out.println("Do your thing here");
}
}
}
public void stop(){
shouldCheckUpdates = false;
}
Thread.stop is deprecated so how do we stop a thread in java ?
Always use interrupt method and future to request cancellation
When the task responds to interrupt signal, for example, blocking queue take method.
Callable < String > callable = new Callable < String > () {
#Override
public String call() throws Exception {
String result = "";
try {
//assume below take method is blocked as no work is produced.
result = queue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return result;
}
};
Future future = executor.submit(callable);
try {
String result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
logger.error("Thread timedout!");
return "";
} finally {
//this will call interrupt on queue which will abort the operation.
//if it completes before time out, it has no side effects
future.cancel(true);
}
When the task does not respond to interrupt signal.Suppose the task performs socket I/O which does not respond to interrupt signal and thus using above approach will not abort the task, future would time out but the cancel in finally block will have no effect, thread will keep on listening to socket. We can close the socket or call close method on connection if implemented by pool.
public interface CustomCallable < T > extends Callable < T > {
void cancel();
RunnableFuture < T > newTask();
}
public class CustomExecutorPool extends ThreadPoolExecutor {
protected < T > RunnableFuture < T > newTaskFor(Callable < T > callable) {
if (callable instanceof CancellableTask)
return ((CancellableTask < T > ) callable).newTask();
else
return super.newTaskFor(callable);
}
}
public abstract class UnblockingIOTask < T > implements CustomCallable < T > {
public synchronized void cancel() {
try {
obj.close();
} catch (IOException e) {
logger.error("io exception", e);
}
}
public RunnableFuture < T > newTask() {
return new FutureTask < T > (this) {
public boolean cancel(boolean mayInterruptIfRunning) {
try {
this.cancel();
} finally {
return super.cancel(mayInterruptIfRunning);
}
}
};
}
}
After 15+ years of developing in Java there is one thing I want to say to the world.
Deprecating Thread.stop() and all the holy battle against its use is just another bad habit or design flaw unfortunately became a reality... (eg. want to talk about the Serializable interface?)
The battle is focusing on the fact that killing a thread can leave an object into an inconsistent state. And so? Welcome to multithread programming. You are a programmer, and you need to know what you are doing, and yes.. killing a thread can leave an object in inconsistent state. If you are worried about it use a flag and let the thread quit gracefully; but there are TONS of times where there is no reason to be worried.
But no.. if you type thread.stop() you're likely to be killed by all the people who looks/comments/uses your code. So you have to use a flag, call interrupt(), place if(!flag) all around your code because you're not looping at all, and finally pray that the 3rd-party library you're using to do your external call is written correctly and doesn't handle the InterruptException improperly.
I'm using a thread that is continuously reading from a queue.
Something like:
public void run() {
Object obj;
while(true) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}
What is the best way to stop this thread?
I see two options:
1 - Since Thread.stop() is deprecated, I can implement a stopThisThread() method that uses a n atomic check-condition variable.
2 - Send a Death Event object or something like that to the queue. When the thread fetches a death event, it exits.
I prefer the 1st way, however, I don't know when to call the stopThisThread() method, as something might be on it's way to the queue and the stop signal can arrive first (not desirable).
Any suggestions?
The DeathEvent (or as it is often call, "poison pill") approach works well if you need to complete all of the work on the queue before shutting down. The problem is that this could take a long time.
If you want to stop as soon as possible, I suggest you do this
BlockingQueue<O> queue = ...
...
public void run() {
try {
// The following test is necessary to get fast interrupts. If
// it is replaced with 'true', the queue will be drained before
// the interrupt is noticed. (Thanks Tim)
while (!Thread.interrupted()) {
O obj = queue.take();
doSomething(obj);
}
} catch (InterruptedException ex) {
// We are done.
}
}
To stop the thread t that instantiated with that run method, simply call t.interrupt();.
If you compare the code above with other answers, you will notice how using a BlockingQueue and Thread.interrupt() simplifies the solution.
I would also claim that an extra stop flag is unnecessary, and in the big picture, potentially harmful. A well-behaved worker thread should respect an interrupt. An unexpected interrupt simply means that the worker is being run in a context that the original programmer did not anticipate. The best thing is if the worker to does what it is told to do ... i.e. it should stop ... whether or not this fits with the original programmer's conception.
Why not use a scheduler which you simply can stop when required? The standard scheduler supports repeated scheduling which also waits for the worker thread to finish before rescheduling a new run.
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(myThread, 1, 10, TimeUnit.SECONDS);
this sample would run your thread with a delay of 10 sec, that means when one run finishes, it restarts it 10 seconds later. And instead of having to reinvent the wheel you get
service.shutdown()
the while(true) is not necessary anymore.
ScheduledExecutorService Javadoc
In your reader thread have a boolean variable stop. When you wish for this thread to stop set thius to true and interrupt the thread. Within the reader thread when safe (when you don't have an unprocessed object) check the status of the stop variable and return out of the loop if set. as per below.
public class readerThread extends Thread{
private volitile boolean stop = false;
public void stopSoon(){
stop = true;
this.interrupt();
}
public void run() {
Object obj;
while(true) {
if(stop){
return;
}
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(stop){
return;
}
obj = objectesQueue.poll();
// Do something with the Object obj
}
}
}
}
public class OtherClass{
ThreadReader reader;
private void start(){
reader = ...;
reader.start();
}
private void stop(){
reader.stopSoon();
reader.join(); // Wait for thread to stop if nessasery.
}
}
Approach 1 is the preferred one.
Simply set a volatile stop field to true and call interrupt() on the running thread. This will force any I/O methods that wait to return with an InterruptedException (and if your library is written correctly this will be handled gracefully).
I think your two cases actually exhibit the same potential behavior. For the second case consider Thread A adds the DeathEvent after which Thread B adds a FooEvent. When your job Thread receives the DeathEvent there is still a FooEvent behind it, which is the same scenario you are describing in Option 1, unless you try to clear the queue before returning, but then you are essentially keeping the thread alive, when what you are trying to do is stop it.
I agree with you that the first option is more desirable. A potential solution would depend on how your queue is populated. If it is a part of your work thread class you could have your stopThisThread() method set a flag that would return an appropriate value (or throw Exception) from the enqueuing call i.e.:
MyThread extends Thread{
boolean running = true;
public void run(){
while(running){
try{
//process queue...
}catch(InterruptedExcpetion e){
...
}
}
}
public void stopThisThread(){
running = false;
interrupt();
}
public boolean enqueue(Object o){
if(!running){
return false;
OR
throw new ThreadNotRunningException();
}
queue.add(o);
return true;
}
}
It would then be the responsibility of the object attempting to enqueue the Event to deal with it appropriately, but at the least it will know that the event is not in the queue, and will not be processed.
I usually put a flag in the class that has the Thread in it and in my Thread code I would do. (NOTE: Instead of while(true) I do while(flag))
Then create a method in the class to set the flag to false;
private volatile bool flag = true;
public void stopThread()
{
flag = false;
}
public void run() {
Object obj;
while(flag) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}
I have a class proposing translations utilities. The translations themselves should be reloaded every 30 minutes. I use Spring Timer support for that. Basically, my class looks like :
public interface Translator {
public void loadTranslations();
public String getTranslation(String key);
}
loadTranslations() can be pretty long to run, so while it is running the old translations are still available. This is done by loading the translations in a local Map and just changing the reference when all translations are loaded.
My problem is : how do I make sure that when a thread is already loading translations, is a second one also tries to run, it detects that and returns immediately, without starting a second update.
A synchronized method will only queue the loads ... I'm still on Java 1.4, so no java.util.concurrent.
Thanks for your help !
Use some form of locking mechanism to only perform the task if it is not already in progress. Acquiring the locking token must be a one-step process. See:
/**
* #author McDowell
*/
public abstract class NonconcurrentTask implements Runnable {
private boolean token = true;
private synchronized boolean acquire() {
boolean ret = token;
token = false;
return ret;
}
private synchronized void release() {
token = true;
}
public final void run() {
if (acquire()) {
try {
doTask();
} finally {
release();
}
}
}
protected abstract void doTask();
}
Test code that will throw an exception if the task runs concurrently:
public class Test {
public static void main(String[] args) {
final NonconcurrentTask shared = new NonconcurrentTask() {
private boolean working = false;
protected void doTask() {
System.out.println("Working: "
+ Thread.currentThread().getName());
if (working) {
throw new IllegalStateException();
}
working = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!working) {
throw new IllegalStateException();
}
working = false;
}
};
Runnable taskWrapper = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
shared.run();
}
}
};
for (int i = 0; i < 100; i++) {
new Thread(taskWrapper).start();
}
}
}
I am from a .net background(no java experience at all), but you could try a simple static flag of some sort that checks at the beginning of the method if its alrady running. Then all you need to do is make sure any read/write of that flag is synchronized. So at beginning check the flag, if its not set, set it, if it is set, return. If its not set, run the rest of the method, and after its complete, unset it. Just make sure to put the code in a try/finally and the flag iunsetting in the finally so it always gets unset in case of error. Very simplified but may be all you need.
Edit: This actually probably works better than synchronizing the method. Because do you really need a new translation immediately after the one before it finishes? And you may not want to lock up a thread for too long if it has to wait a while.
Keep a handle on the load thread to see if it's running?
Or can't you just use a synchronized flag to indicate if a load is in progress?
This is actually identical to the code that is required to manage the construction of a Singleton (gasp!) when done the classical way:
if (instance == null) {
synchronized {
if (instance == null) {
instance = new SomeClass();
}
}
}
The inner test is identical to the outer test. The outer test is so that we dont routinely enter a synchronised block, the inner test is to confirm that the situation has not changed since we last made the test (the thread could have been preempted before entering Synchronized).
In your case:
if (translationsNeedLoading()) {
synchronized {
if (translationsNeedLoading()) {
loadTranslations();
}
}
}
UPDATE: This way of constructing a singleton will not work reliably under your JDK1.4. For explanation see here. However I think you are you will be OK in this scenario.