I have a following code as below:
new Thread(new Test1Runnable()).start(); // Line (a)
public class Test1Runnable implements Runnable {
public void run() {
Test2Runnable task1 = new Test2Runnable();
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
executor.submit(task1);
while(true) {
if(task1.isDone()) {
break;
}
// Thread.sleep(2000); // Line (b)
}
if(!task1.hasError()) { // Line (c)
executor.submit(new Test3Runnable());
}
} catch(Exception ex) {
if(executor != null) {
executor.shutdown();
}
}
}
}
public class Test2Runnable implements Runnable {
private Exception error;
private boolean done;
public void run() {
reset();
doRun();
done = true;
}
protected void doRun() {
try{
// ...
// ....
} catch(Exception ex) {
}
}
private void reset() {
error = null;
done = false;
}
public boolean isDone() {
return done;
}
public boolean hasError() {
return getError() != null || getNonSuccess() > 0;
}
public Exception getError() {
return error;
}
}
I have an issue when I run Test1Runnable at line (a) and comment Line (b) then the thread hang and not run to Line (c). If I uncomment line (b) or I add breakpoint at line (c) and activate remote debug the thread continue to run to the end as normal. Could anyone can give me some advice about this? Why the Thread not continue running? All threads run without any exception.
Looks like you have a race conditioin here, so result of the execution depends on timings, debug enabled, etc. The code posted is more or less fine, the error is likely to be in Test2Runnable class. I suppose there are some flags (isDone, hasError) that have visibility issues. Try to declare them volatile.
Please add Test2Runnable code here and I'll be able to give more precise answer.
Related
I am trying to create a simple example with async CompletableFuture's but I'm seeing some weird behaviour. The idea is that I kick off 2 async futures, one activates a boolean flag after a set time and the other polls that flag to release the value once thread 1 has changed that flag. Here's my code:
package completablefutures;
import java.util.concurrent.CompletableFuture;
public class CFMain throws InterruptedException {
public static void main(String... args) {
CF cf = new CF();
CompletableFuture.supplyAsync(cf::getCompletable).thenRun(() -> System.out.println("Post-future action"));
CompletableFuture.supplyAsync(cf::doSleep);
Thread.sleep(10000);
}
}
And the CF class:
package completablefutures;
public class CF {
private boolean valueIsSafe = false;
public boolean getCompletable() {
System.out.println("Fetching completable");
while(true) {
if(this.valueIsSafe) {
System.out.println("Completable fetched");
return true;
}
}
}
public boolean doSleep() {
System.out.println("Started sleeping");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.valueIsSafe = true;
System.out.println("Finished sleeping");
return true;
}
}
When I let the program run it's course, it prints this:
Fetching completable
Started sleeping
Finished sleeping
Process finished with exit code 0
i.e. the future never completes in the 10s allocated. So what's going on here?
You are accessing the valueIsSafe from multiple threads, you must define this variable as volatile.
private volatile boolean valueIsSafe = false;
Using the volatile keyword will prevent threads from caching this value and force them to read the raw memory on every access.
This is because you are not using a thread safe data type, you can change your code to use AtomicBoolean here is an example of your code using AtomicBoolean:
public class CF {
private AtomicBoolean valueIsSafe = new AtomicBoolean (false);
public boolean getCompletable() {
System.out.println("Fetching completable");
while(true) {
if(this.valueIsSafe.get()) {
System.out.println("Completable fetched");
return true;
}
//System.out.println("doing something");
}
}
public boolean doSleep() {
System.out.println("Started sleeping");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.valueIsSafe.set(true);
System.out.println("Finished sleeping");
return true;
}
}
I have started threads in sequence but i don't know how to stop them in reverse sequence.
For example:
they are starting like this: A->B->C->D
and I want them to stop: D->C->B->A
I don't know how to stop threads at all and not even in this order.
I appreciate any help or advice.
import java.util.*;
class Service extends Thread
{
private RobotController controller;
private String robotID;
private byte[] lock;
public Service(RobotController cntrl, String id)
{
controller = cntrl;
robotID = id;
}
public byte[] getLock() { return lock;}
public void run()
{
lock = new byte[0];
synchronized(lock)
{
byte[] data;
while ((data = controller.getData()) == null)
{
try {
lock.wait();
} catch (InterruptedException ie) {}
}
System.out.println("Robot " + robotID + " Working");
}
}
}
class RobotController
{
private byte[] robotData;
private Vector threadList = new Vector();
private Service thread_A;
private Service thread_B;
private Service thread_C;
private Service thread_D;
private volatile boolean done;
public void setup(){
thread_A = new Service(this, "A");
thread_B = new Service(this, "B");
thread_C = new Service(this, "C");
thread_D = new Service(this, "D");
threadList.addElement(thread_A);
threadList.addElement(thread_B);
threadList.addElement(thread_C);
threadList.addElement(thread_D);
thread_A.start();
thread_B.start();
thread_C.start();
thread_D.start();
start();
stop();
}
public void start()
{
System.out.println("Thread starts");
{
for (int i=0; i <= 3; i++)
{
try {
Thread.sleep(500);
}catch (InterruptedException ie){}
putData(new byte[10]);
Service rbot = (Service)threadList.elementAt(i);
byte[] robotLock = rbot.getLock();
synchronized(robotLock) {
robotLock.notify();
}
}
}
}
public void stop()
{
{
}
}
public synchronized byte[] getData()
{
if (robotData != null)
{
byte[] d = new byte[robotData.length];
System.arraycopy(robotData, 0, d, 0, robotData.length);
robotData = null;
return d;
}
return null;
}
public void putData(byte[] d) { robotData = d;}
public static void main(String args[])
{
RobotController controller = new RobotController();
controller.setup();
}
}
I'll usually include something like a cancel() method in my threads if I want to explicitly terminate them.
class Service extends Thread {
private volatile boolean cancel = false;
public void cancel() {
cancel = true;
}
public void run() {
...
while (!cancel && (data = controller.getData()) == null) {
...
}
}
}
Keep your threads in a stack as mre suggests, then pop through the stack and call cancel and then interrupt on each thread.
I have started threads in sequence but i don't know how to stop them in reverse sequence.
This is difficult to do. There are ways you can stop a thread either by setting a volatile shutdown boolean or interrupting them, but none of these mechanisms are guaranteed to stop a thread immediately.
You certainly can keep a List<Thread> when you build them, call Collections.reverse(threadList) and then call thread.interrupt() on each one in turn. If you must have them finish in order then you should interrupt() them and then join them. Something like:
Collections.reverse(threadList);
for (Thread thread : threadList) {
thread.interrupt();
thread.join();
}
Then each thread should be doing something like:
while (!Thread.currentThread().isInterrupted()) {
...
}
Note that if you are running Thread.sleep(...) or other methods that throw InterruptedException, you'll need to re-enable the interrupt flag:
try {
Thread.sleep(...);
} catch (InterruptedException e) {
// by convention if InterruptedException thrown, interrupt flag is cleared
Thread.currentThread().interrupt();
...
}
Have each thread keep a reference to the next thread to be started. Then each thread can periodically check to see if the thread is still alive. If not, that thread should terminate. When it does, the previous thread will notice and terminate, and so on up the chain.
abstract class ChainThread extends Thread {
private final Thread next;
ChainThread(Thread next) { this.next = next; }
#Override
public final void run() {
next.start();
while (!Thread.currentThread().isInterrupted() && next.isAlive()) {
do();
}
}
abstract void do();
}
If I read the Service code correctly, it waits until there's data to execute on, then finishes. So you don't really need an explicit stop or cancel type signal, the threads will terminate themselves after they do work.
To enforce ordering of shutdown, you could make each Service aware of the previous Service, and then call previousService.join(). Assuming no InterruptedExceptions are thrown, they will then shutdown in order after seeing that the controller has data.
Create the Services this way:
Service serviceA = new Service(controller, "A", null);
Service serviceB = new Service(controller, "B", serviceA);
Service serviceC = new Service(controller, "C", serviceB);
Service serviceD = new Service(controller, "D", serviceC);
and the implementation is edited to exit only after dependent Services are complete:
private final RobotController controller;
private final String robotID;
private byte[] lock;
private final Service dependentService;
public Service(RobotController cntrl, String id, Service dependentService) {
controller = cntrl;
robotID = id;
this.dependentService = dependentService;
}
public byte[] getLock() {
return lock;
}
#Override
public void run() {
lock = new byte[0];
synchronized (lock) {
byte[] data;
while ((data = controller.getData()) == null) {
try {
lock.wait();
}
catch (InterruptedException ie) {
}
}
System.out.println("Robot " + robotID + " Working");
}
if (dependentService != null) {
try {
dependentService.join();
}
catch (InterruptedException e) {
this.interrupt();
}
}
}
I'm trying to implement a piece of code to synchronously start looped service in Java. The idea is, code under // STARTER comment should be considered as piece of Service.go() method, so if service fails to start, I want to re-throw the exception synchronously. That piece of code should only finish in case I've tried to start the thread, waited until its execution flow reached some point and next, if there are no problems, my go() method quits and thread goes on, or, if there were problems, I can re-throw the exception caught in thread's run() method from my go() method. Here's the solution that seems to work fine, but I'm curious if it's possible to make it a couple times shorter :-)
public class Program {
private static boolean started;
private static Throwable throwable;
public static void main(String[] args) {
final Object startedSetterLock = new Object();
Thread thread = new Thread() {
public void run() {
System.out.printf("trying to start...\n");
boolean ok;
Throwable t = null;
try {
init();
ok = true;
} catch(Exception e) {
ok = false;
t = e;
}
synchronized(startedSetterLock) {
started = ok;
throwable = t;
startedSetterLock.notifyAll();
}
if(!ok) {
return;
}
while(true) {
try {
System.out.printf("working...\n");
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.printf("interrupted\n");
}
}
}
private void init() throws Exception { throw new Exception(); } // may throw
};
// STARTER
synchronized(startedSetterLock) {
thread.start();
try {
startedSetterLock.wait();
} catch(InterruptedException e) {
System.out.printf("interrupted\n");
}
}
// here I'm 100% sure that service has either started or failed to start
System.out.printf("service started: %b\n", started);
if(!started) {
throwable.printStackTrace();
}
}
}
And also, there's a reason to have initialization code executed within that thread, so, please, don't advise running initialization code explicitly in go() method and then just passing all the stuff to the thread.
Thanks!
How about overriding the Thread.start() method?
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
while (true) {
try {
System.out.printf("working...\n");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.printf("interrupted\n");
}
}
}
#Override
public synchronized void start() {
try {
init();
} catch (Exception e) {
throw new RuntimeException(e);
}
super.start();
}
private void init() throws Exception {
throw new Exception("test");
}
};
t.start();
}
I had came across different suggestion of stopping a thread. May I know, which is the correct way? Or it depends?
Using Thread Variable http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
Using boolean flag
private volatile boolean flag;
public void stop() {
flag = false;
}
public void run() {
while (flag) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
Using Thread Variable together with interrupt
private volatile Thread blinker;
public void stop() {
blinker.interrupt();
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (!thisThread.isInterrupted() && blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
None of these is the "correct" way, they're all valid. Which one you use depends on your circumstances, and which one works best for you.
As long as you don't use Thread.stop(), and you tidy up any resources left open by your threads (connections, temp files, etc), then it doesn't really matter how you go about it.
I always use the boolean flag - its the simplest.
Its really short and easy to understand for reviewers, but it has the handycap that you can't interrupt the sleep call. You should only use the interrupt variants for time-critical thread stopping. And, like skaffman said - Don't use Thread.stop()!
what about this
class Tester {
public static void main() {
Try t = new Try();
Thread.sleep(10); //wait for 10 milliseconds
t.interrupt(); // 'interrupt' i.e stop the thread
}
}
public class Try extends Thread {
#override
public void interrupt() {
//perform all cleanup code here
this.stop();
/*stop() is unsafe .but if we peform all cleanup code above it should be okay ???. since thread is calling stop itself?? */
}
}
I need to run two SwingWorkers. One of them can only run after the other is done. Can I run them like this?
class TestWorker {
private FirstWorker worker1;
private SecondWorker worker2;
public TestWorker() {
worker1 = new FirstWorker() {
#Override
protected void done() {
try {
result1 = get();
} catch (Exception) {
// exception handling
}
worker2 = new SecondWorker() {
#Override
protected void done() {
try {
result2 = get();
} catch (Exception) {
// exception handling
}
}
}
worker2.execute();
}
}
worker1.execute();
}
}
And how should I cancel them? Like this?
private cancel() {
if (worker2 != null) work2.cancel();
if (worker1 != null) work1.cancel();
}
Thanks a lot!
You can do it that way and it will work. However, unless there are other operations in your outer done that you're not showing, you would probably be better off with something that did both operations in doInBackground and returned an array of the results.