Not sure I understand threads correctly, could someone tell me whether I´m right or wrong in the following example:
class Task {
String taskName;
private Thread thread;
boolean isFinished;
public Task(String name){
taskName = name;
}
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
};
thread.start();
}
}
What I'm actually doing in my app is that I set the isFinished to true, and have an observer that whenever the isFinished is true does some stuff. I'm afraid that isFinished is set to true, before all code in the Runnable I pass as parameter is actually terminated.
Isn't the run method suppose to put the code I pass, in a separate thread and run that code asynchronously?
Close, but your new thread is already given the runnable object to execute. You really want to give it a wrapper which runs the r.run() method and then sets isFinished.
Change:
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
};
thread.start();
}
to
public void createTask(final Runnable r) {
thread = new Thread( new Runnable {
public void run(){
if(r != null) {
r.run();
isFinished = true;
}
}
});
thread.start();
}
I would be remiss if I didn't point out the thread-unsafetiness of isFinished. You will not be guaranteed to notice when the thread finishes, without adding synchronization. I recommend you add:
public synchronized boolean getIsFinished()
{
return isFinished;
}
public synchronized void setIsFinished(boolean finished)
{
isFinished = finished;
}
And use these methods to get or set the isFinished flag.
Given your lack of synchronization here, you may be seeing other thread-safety oddities, depending on whether or not your r.run() method and your other "observer" are sharing data without synchronization as well.
You should almost never pass a Runnable into the constructor of a Thread and override the Thread's run() method.
The following two pieces of code are essentially identical:
Runnable r = new Runnable( )
{
public void run( )
{
// do stuff...
}
};
new Thread( r ).start( );
An here's another way to accomplish the same thing by overriding run():
(new Thread( )
{
public void run( )
{
// do stuff...
}
}).start( );
The way you wrote your code, isFinished will not be set to true until r.run() is complete. It may be appearing otherwise because you may have some data visibility issues due to missing synchronization or missing volatile declarations.
It's a little bit odd since you're both passing in the Runnable to the constructor, but calling it using the reference from your method declaration, not the one inside the thread. But it "works", there's just a redundancy there.
As an aside, don't forget #Override in your anonymous class :)
No, the run method simply is a normal function, that you can override when extending the Thread class in order to implement your own behaviour.
It's the start method of the Thread class that starts a new thread and runs that code async.
Well your code is partially right, and partially wrong.
You are correct that isFinished will only be set to true once everything inside the runnable you are passing in the parameter has finished executing.
However, due to the particular semantics of the java memory model (I'll get into more details about that below), it is possible that when you set isFinished to true, that change is only visible to the thread that has set that variable to true. If you want your code to work as expected, you need to declare isFinished as volatile. This will make any changes you make to that variable immediately visible by other threads.
Another way to do it is to declare isFinished as AtomicBoolean rather than boolean. This class has many methods that allow you to check and set the boolean in an atomic way, helping you to avoid many common multithreading pitfalls.
I suggest you use the synchronization primitive specifically designed for your problem.
This primitive is called CountDownLatch.
Here is the updated code:
class Task {
String taskName;
private Thread thread;
CountDownLatch finishedSignal = new CountDownLatch( 1 );
public Task(String name){
taskName = name;
}
public void createTask(final Runnable r) {
thread = new Thread(r){
public void run(){
if(r != null) {
r.run();
finishedSignal.countDown( );
}
}
};
thread.start();
finishedSignal.await( );
}
}
You should use a FutureTask instead of your own Task class. It has an isDone() method, and it is integrated nicely with the Executor framework.
Most importantly the happens-before relationships are maintained as you expect it (actually in your code the problem is not that isFinished is set to true, before all code in the Runnable is terminated, but the other way: possibly it will not be set to true in the original thread even if the Runnable is terminated)
Example:
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("work done");
}
};
FutureTask<Void> task = new FutureTask<Void>(runnable, null);
ExecutorService es = Executors.newSingleThreadExecutor();
es.submit (task);
while (!task.isDone()) {
System.out.println("waiting...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Related
I was doing some thought experiment and here is my MyRunnable class:
class MyRunnable implements Runnable {
private final Integer mNumber;
private final CompleteHandler<Integer> mCallback;
public MyRunnable(Integer i, CompleteHandler<Integer> ch) {
mNumber = i;
mCallback = ch;
}
public void run() {
int sum = 0;
for (int i = 1; i <= mNumber; i++) {
sum += i;
}
mCallback.onFinished(sum);
}
}
This will be executed by a background thread which I create on the main thread, under the execute() method
public class Demo implements CompleteHandler<Integer>{
public static void main(String[] args) {
Demo d = new Demo();
d.execute();
}
#Override
public void onFinished(Integer i) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName); // thread-0
}
public void execute() {
MyRunnable mr = new MyRunnable(10, this);
Thread t = new Thread(mr);
t.start();
}
}
As you can see, the MyRunnable calls onFinished() when the task is finished. Is there any way I can have the background thread to call this on the main thread? I know I can do similar thing with callables, but right now I want to know if this is possible with runnables,
thank you
Johannes: Take a look at CompletableFuture...
Brendon: I'm more interested in seeing how it work on code
Here's a simplistic implementation that ignores the issue of exceptions. (Pardon me if it's not actually valid Java code.)
class CompletableFuture<ValueType> {
private Object lock = new Object();
private boolean is_completed = false;
private ValueType completed_value;
public synchronized void complete(ValueType v) {
completed_value = v;
is_completed = true;
notifyAll();
}
public synchronized ValueType await() {
while (! is_completed) {
wait();
}
return completed_value;
}
}
The idea is, the client thread creates a CompletableFuture instance, cf, and somehow passes it to the server thread, possibly along with other args that tell the server thread what to do. Then the client thread goes off to do other, unrelated things.
Meanwhile, the server thread does its thing, eventually produces a result, r, and then it calls cf.complete(r).
At some point, the client thread finishes doing whatever else it was doing, and now it needs the result, so it calls cf.await(). Either one of two things happen at that point:
The server already has set the is_completed flag, in which case, the client immediately gets the result, OR
The server has not yet finished, so the client goes in to the wait() loop to wait for it.
When you're looking at application code, you usually never see the part where the client thread creates the Future object or passes it to the other thread. That usually is all taken care of inside the library call when the client submits a task to a thread pool.
I want to pause and start thread untill variable standby.
But wait() and notify() is not work for me.
Is this a collect way to pause thread?
private boolean _threadIsWaiting = true;
private Object _specialObjectFromHttp;
public void methodToUse() {
Thread thread = new Thread(new Runnable() {
getParamsFromHttp();
while (_threadIsWaiting) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
convertObject(_specialObjectFromHttp);
)};
}
// Callback method (Thread wait for this.)
private void getParamsFromHttpCallBack(Object result) {
_specialObjectFromHttp = result;
_threadIsWaiting = false;
}
You could use an object to wait on, and call notify on it. I believe that to be the better approach (Actually, it is almost always better to utilize such a mechanism instead of sleeping and bool checking).
private Object _specialObjectFromHttp;
public void methodToUse() {
Thread thread = new Thread(new Runnable() {
getParamsFromHttp();
_specialObjectFromHttp.wait();
)};
}
// Callback method (Thread wait for this.)
private void getParamsFromHttpCallBack(Object result) {
_specialObjectFromHttp = result;
_specialObjectFromHttp.notifyAll();
}
In this case it seems plausible to just use the object that is being used in that control flow anyways, but you could also just add another object that has no purpose other than being waited for.
You could use a SynchronousQueue this will block until the information you need is provided. So in one thread call take, this will wait for a put on a different thread.
Both methods are blocking and no manual syncing is needed.
I have a task x that is executed continuously in a thread which will only stop when the boolean changes it's state to true. I have done some reading and there are 3 ways that I approach when killing threads that are in the code below. Which of the 3 methods is effective ? And if none of them aren't effective or correct kindly suggest a proper approach with some code for reference.
Below is the code :
public class MyTest {
private static class transaction {
private String param1,param2,param3, param4, param5;
public transaction (String param1,String param2,String param3,String param4,String param5){
this.param1=param1;
this.param2=param2;
this.param3=param3;
this.param4=param4;
this.param5=param5;
}
public String getParam1(){
return this.param1;
}
public String getParam2(){
return this.param2;
}
public String getParam3(){
return this.param3;
}
public String getParam4(){
return this.param4;
}
public String getParam5(){
return this.param5;
}
}
public static void processBatch(String workerName){
try{
java.util.List <transaction> transactions= new java.util.LinkedList<transaction>();
java.sql.ResultSet dbtrx=Database.db.execQuery((Object)"dbname.procname");
while(dbtrx.next()){// Takes a snapshot of the pending payments in the table and stores it into the list.
Object obj=new transaction (dbtrx.getString("col1"), dbtrx.getString("col2"), dbtrx.getString("col3"), dbtrx.getString("col4"), dbtrx.getString("col5"));
transactions.add((transaction)obj);
obj=null;
}
java.util.Iterator<transaction> iterate= transactions.iterator();
/* Processes the pending batch payments*/
while(iterate.hasNext()){
transaction trx=iterate.next();
/*Calls posting function here*/
System.out.println(workerName+":- Param1 : "+trx.getParam1()+" - Param2 : " +trx.getParam2()+
" - Param3 : "+ trx.getParam3()+" - Param4 : "+ trx.getParam4()+" - Param5 : "+ trx.getParam5());
iterate.remove();
}
/*cleaning object references*/
dbtrx=null;
transactions=null;
iterate=null;
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String [] args) throws InterruptedException{
volatile boolean stop=false;
Object hold= new Object();
new Thread("Batch Worker A"){
#Override
public void run(){
while(true){
if(stop!=true){
processBatch(Thread.currentThread().getName());
}else{
try{
Thread.sleep(0);
Thread.currentThread().interrupt();
}catch(java.lang.InterruptedException e){
Thread.currentThread().interrupt();
break;
}
}
}
}}.start();
new Thread("Batch Worker B"){
#Override
public void run(){
try{
while(stop!=true){
processBatch(Thread.currentThread().getName());
}
Thread.sleep(0);
Thread.currentThread().interrupt();
}catch(java.lang.InterruptedException e){
Thread.currentThread().interrupt();
}
}}.start();
new Thread("Batch Worker C"){
#Override
public void run(){
while(!Thread.currentThread().isInterrupted()){
if(stop!=true){
processBatch(Thread.currentThread().getName());
}else{
Thread.currentThread().interrupt();
}
}
}}.start();
}
}
}
The recommended approach is to use the thread's interrupted flag to signal the thread loop to terminate. There's no reason to use two flags (stopped and the interrupted flag) where one will do, and you don't seem to be using the interrupted flag for anything else.
See the Java tutorial subject Interrupts for a more extensive discussion and examples.
Why not simply this way:
new Thread("Batch Worker A"){
#Override
public void run() {
while(!stop){
processBatch(Thread.currentThread().getName());
}
}
}}.start();
Alternatively, use Thread.interrupt() like so:
new Thread("Batch Worker A"){
#Override
public void run() {
while(!interrupted()){
processBatch(Thread.currentThread().getName());
}
}
}}.start();
but then you need to keep reference to all the threads, and interrupt them all, so the boolean flag might be simpler (be sure to make it volatile).
In all of your examples, you aren't really killing the thread, you are stopping the batch from processing more items.
To understand the difference, note that none of your methods would actually stop the thread while the thread is within the processBatch function.
There are some things to take note of:
There is no point in calling Interrupt() on your current thread. The idea behind Interrupt is for external threads to call it. In your case, you can just as well throw an exception, or return from the run() function (which would shut down the thread automatically).
Even interrupt() can't in many situations stop a thread if that thread is locked outside java ,such as thread waiting for IO (if not using NIO), including a socket, which is what the database connection is, you'll need to design a different way to stop a thread inside IO (usually by doing a timeout, but there are other ways).
if you goal is simply to stop the next batch from happing use the code from Joonas :
new Thread("Batch Worker A"){
#Override
public void run() {
while(!stop){
processBatch(Thread.currentThread().getName());
}
}
}}.start();
if your goal is to interrupt the process while running the batch, you can just as well do:
public static void main(String[] args) {
var t =new Thread("Batch Worker A"){
#Override
public void run() {
processBatch(Thread.currentThread().getName());
}
}.start();
t.interrupt();
}
in general interrupt is the preferred method, and using a local scoped variable and anonymous classes is a really bad idea (use a static variable, or better an injected interface with a function to check if the thread should continue).
Isn't it possible that notify() in another thread gets called before the wait() in one thread?
It's happening with me.
A client requests a value from a target and waits on a result variable RV.
In case the target is the client itself, I update RV with the correct result and call notify() on RV in another thread.
class EMU {
ResultVar RV;
Address my_address;
ResultVar findValue(String key) {
String tgt = findTarget(key);
sendRequest(tgt, key);
synchronized(RV) {
RV.wait();
}
return RV;
}
Runnable Server = new Runnable() {
public void run() {
//code to receive connections. Assume object of type Request is read from the stream.
Request r = (Request) ois.readObject();
if(r.requesterAddr.compareTo(my_address) == 0) {
String val = findVal(key);
RV.putVal(val);
synchronized(RV){
RV.notify();
}
}
}
};
}
The problem is that before the requester has completed all the "networking" (sendReqest in the above example) with itself, the result is updated in the result variable. When the requester thread now calls wait(), the program doesn't continue, since notify has already been called.
How can we prevent it?
You check some flag before waiting (in a loop), see the tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
Nothing stops you calling notify on an object that's not being waited by another thread.
It sounds like what you want is a wait only if some condition holds. For example:
synchronized (results) {
while (!results.hasResults()) {
// no results yet; wait for them
try {
results.wait();
} catch (InterruptedException ie) { /* ignore */ }
}
}
I'd strongly recommend not re-inventing the wheel.
Java's Future interface is designed for results that may only arrive later, and the FutureTask class implements this interface.
Have the first thread obtain access to the Future and get the second thread to run the FutureTask, and all of this stuff gets handled for you. You also get timeout support for free.
Use some condition before going to wait() and make sure that condition is thread safe :)
class EMU{
ResultVar RV;
Address my_address;
volatile boolean condition = true;
ResultVar findValue(String key){
String tgt = findTarget(key);
sendRequest(tgt, key);
synchronized(RV){
while(condition == true)
{
RV.wait();
}
}
return RV;
}
Runnable Server = new Runnable(){
public void run(){
//code to receive connections. Assume object of type Request is read from the stream.
Request r = (Request) ois.readObject();
if(r.requesterAddr.compareTo(my_address) == 0){
String val = findVal(key);
RV.putVal(val);
synchronized(RV){
condition = false;
RV.notify();
}
}
}
};
Let me first break down the code to a minimum reproducable:
public static void main(String[] args) throws Exception {
Object RV = new Object();
new Thread() {
#Override
public void run() {
synchronized (RV) {
RV.notify();
}
}
}.start();
Thread.sleep(1_000);
synchronized (RV) {
RV.wait();
}
}
This method will theoretically never end and the program will never quit. It shall be a dispute if this is a deadlock.
My solution is to create a second lock:
public static void main(String[] args) throws Exception {
Object RV = new Object();
Object lock = new Object();
new Thread() {
#Override
public void run() {
synchronized (lock) {
lock.wait();
}
synchronized (RV) {
RV.notify();
}
}
}.start();
Thread.sleep(1_000);
synchronized (RV) {
synchronized (lock) {
lock.notify();
}
RV.wait();
}
}
Lets inspect what the threads are doing while the main-thread is waiting one second:
The custom Thread will first join the synchronized(lock) block.
Then the lock will causes the custom Thread to wait.
After 1 second the main-thread is joining a RV-synchronization.
The lock gets notified and causes the custom Thread to continue the work.
The custom thread leaves the synchronized(lock) block.
The main thread will RV-wait-lock.
The custom thread notifies the RV-lock to continue.
The program ends.
In the below code, when I execute the producercon class, sometimes the execution stucks, looks like a deadlock. But if i make the get_flag () synchronized then there are no such problems.
I cannot figure out how there can be a problem. the flag can either true or false so only one of the producer or consumer will get into the if statement. After one of them enters the if it will enter the monitor with object r (both are initialized with the same object reference). The only problem which can happen that the r object being modified by the increment_decrement () function call, and the get_flag () reading the flag at the same time, but even then it will not enter the if in that iteration, but it will enter the if block on the next iteration, and even if the first thread did not leave the monitor, it will wait there for it (before the synchronized block).
How, and why is the program halting/hanging if get_flag () is not made synchronized ?
import java.io.*;
class resource
{
private boolean res, flag;
resource ()
{
flag=false;
}
boolean get_flag ()
{
return flag;
}
void increment_decrement (String s,boolean t)
{
res=t;
flag=t;
try
{
System.out.print("\n"+s+":"+res);
Thread.sleep(200);
}
catch(InterruptedException e)
{
}
}
}
class producer implements Runnable
{
resource r1;
Thread t1;
producer(resource r)
{
r1 = r;
t1 = new Thread(this);
t1.start();
}
public void run ()
{
while (true)
{
if(r1.get_flag () == false)
{
synchronized(r1)
{
r1.increment_decrement("Producer",true);
}
}
}
}
public void waitForThread () throws InterruptedException
{
t1.join ();
}
}
class consumer implements Runnable
{
resource r2;
Thread t2;
consumer(resource r)
{
r2 = r;
t2 = new Thread (this);
t2.start();
}
public void run()
{
while (true)
{
if(r2.get_flag () == true)
{
synchronized(r2)
{
r2.increment_decrement("Consumer",false);
}
}
}
}
public void waitForThread () throws InterruptedException
{
t2.join ();
}
}
public class producercon
{
public static void main(String args[])
{
try
{
System.out.print("PRESS CTRL+C TO TERMINATE\n");
resource r = new resource();
consumer c = new consumer(r);
producer p = new producer(r);
c.waitForThread ();
p.waitForThread ();
}
catch(InterruptedException e)
{
}
}
}
Your call to get_flag() is not thread safe nor volatile. This means in the cache of thread 1 it can be true while in the cache of thread 2 it can be false.
You need to make your boolean either volatile or an AtomicBoolean. Right now multiple threads are trying to access the boolean that is in no way synchronized.
This producer/consumer implementation is quite weird.
Neither the producer not the consumer wait for the resource to be in the adequate state, and the resource access is not well protected (the flag should be guarded by some lock to ensure its visibility between threads).
One way to improve on this design would be to use the standart wait/notify system. Another way would be to use a Semaphore in the Resource to ensure only one thread can access the resource at one given time. Finally, you could use a higher-level construct such an java.util.concurrent.SynchronousQueue to pass some data directly from the producer to the consumer.