user1769197
user1769197

Reputation: 2213

Java Multi-threading: make a thread to start after checking the returned value from the first thread

I have a thread that basically makes a connection to the server and if the connection is successful, it will return a positive ID number. I would like to create another thread that will check if the current ID number is positive and runs once it detects the ID is positive.

// My first thread that establishes connection 

new Thread() {
    public void run(){
          makeConnection();
          // this makeConnection method will make the ID become a positive number if the connection is fully established.
    }
}.start();

Note that obj.getCurrentId() returns the current ID number. But I am struggling to write the second thread and how it communicates with the first thread. Can someone kindly help me out please? Thanks.

Upvotes: 0

Views: 95

Answers (3)

MGorgon
MGorgon

Reputation: 2597

I recommend using ExecutorService with Callable interface - just return your ID number in Future result.

Have a look at ExecutorService.html#submit

Upvotes: 0

Ravindra babu
Ravindra babu

Reputation: 38910

Few suggestions:

  1. Create an ExecutorService
  2. Submit the first task : ConnectionTask and get the result
  3. Submit the second task: ValidationTask and get the result
  4. Depending on the result you can take next set of actions.

Sample code:

import java.util.concurrent.*;
import java.util.*;

public class CallablePollingDemo{
    public CallablePollingDemo(){
        System.out.println("creating service");
        ExecutorService service = Executors.newFixedThreadPool(2);      
        try{
            Future future1 = service.submit(new ConnectionTask());  
            int result1 = ((Integer)future1.get()).intValue();
            System.out.println("Result from ConnectionTask task:"+result1);
            if ( result1 > 0){ // change this condition to suit your requirement
                Future future2 = service.submit(new ValidationTask(result1));  
                int result2 = ((Integer)future2.get()).intValue();
                System.out.println("Result from ValidationTask task:"+result2);
            }

        }catch(Exception err){
            err.printStackTrace();
        }
        service.shutdown();
    }
    public static void main(String args[]){
        CallablePollingDemo demo = new CallablePollingDemo();
    }
    class ConnectionTask implements Callable<Integer>{

        public ConnectionTask(){

        }
        public Integer call(){
            int id = 1;
            // Add your business logic here , make connection, get the result
            return id;
        }
    }
    class ValidationTask implements Callable<Integer>{
        Integer id = 0;
        public ValidationTask(Integer val){
            this.id = val;
        }
        public Integer call(){
            // Add your verification result ehre
            if ( id > 0 ) {
                return id;
            }else{
                return -1;
            }
        }
    }
}

Upvotes: 0

Nicolas Filotto
Nicolas Filotto

Reputation: 44965

Assuming that you use Java 8 a good way to implement it is with CompletableFuture as it will allow you to define a flow of asynchronous tasks to execute.

So for example here the main code could be:

// Call connect asynchronously using the common pool from a given thread
// then execute someMethod using another thread
CompletableFuture.supplyAsync(MyClass::connect)
    .thenCompose(MyClass::someMethodAsync);

The method connect of the class MyClass could be:

public static int connect() {
    try {
        SomeClass obj = makeConnection();
        // ok so we return a positive value
        return obj.getCurrentId();
    } catch (Exception e) {
        // Do something here
    }
    // ko so we return a negative value
    return -1;
}

The method someMethodAsync of the class MyClass could be:

public static CompletionStage<Void> someMethodAsync(int id) {
    return CompletableFuture.supplyAsync(() -> MyClass.someMethod(id));
}

The method someMethod of the class MyClass could be:

public static Void someMethod(int id) {
    if (id > 0) {
        // do something
    }
    return null;
}

Another approach could be to rely on wait/notify/notifyAll or await/signal/signalAll to notify the other thread that the id has changed.

So your code could be something like that:

public class SomeClass {
    /**
     * The current id
     */
    private int currentId;
    /**
     * The object's monitor
     */
    private final Object monitor = new Object();

    /**
     * @return the current id
     */
    public int getCurrentId() {
        synchronized (monitor) {
            return this.currentId;
        }
    }

    /**
     * Sets the current id and notifies waiting threads
     */
    public void setCurrentId(final int currentId) {
        synchronized (monitor) {
            this.currentId = currentId;
            monitor.notifyAll();
        }
    }

    /**
     * Makes the calling thread wait until the id is positive
     * @throws InterruptedException if current thread is interrupted while waiting
     */
    public void waitForPositiveId() throws InterruptedException {
        synchronized (monitor) {
            while (currentId <= 0) {
                monitor.wait();
            }
        }
    }
}

So your first thread will simply call makeConnection() assuming that internally it calls the setter setCurrentId of SomeClass and the second thread will start by calling waitForPositiveId() to make it wait until the id is positive.

NB: This approach will make the second thread wait for ever if makeConnection() fails.

Upvotes: 1

Related Questions