Java多线程:在检查第一个线程的返回值后,启动一个线程

时间:2016-10-19 17:04:08

标签: java multithreading

我有一个基本上与服务器建立连接的线程,如果连接成功,它将返回一个正ID号。我想创建另一个线程来检查当前ID号是否为正,并在检测到ID为正时运行。

// 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();

请注意obj.getCurrentId()会返回当前的ID号。但我正在努力编写第二个线程以及它如何与第一个线程进行通信。有人可以帮帮我吗?感谢。

3 个答案:

答案 0 :(得分:1)

假设您使用Java 8实现它的好方法是使用CompletableFuture,因为它允许您定义要执行的异步任务流。

例如,这里的主要代码可能是:

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

班级connect的方法MyClass可以是:

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;
}

班级someMethodAsync的方法MyClass可以是:

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

班级someMethod的方法MyClass可以是:

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

另一种方法可能是依靠wait / notify / notifyAllawait / signal / signalAll来通知其他主题id已发生变化。

所以你的代码可能是这样的:

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();
            }
        }
    }
}

所以你的第一个线程只需调用makeConnection(),假设它在内部调用setCurrentId的setter SomeClass,第二个线程将通过调用waitForPositiveId()来启动它以使其等待直到id为正。

NB:如果makeConnection()失败,此方法将使第二个线程等待。

答案 1 :(得分:0)

我建议将ExecutorServiceCallable界面一起使用 - 只需在Future结果中返回您的ID号。

查看ExecutorService.html#submit

答案 2 :(得分:0)

很少有建议:

  1. 创建ExecutorService
  2. 提交第一项任务:ConnectionTask并获得结果
  3. 提交第二项任务:ValidationTask并获得结果
  4. 根据结果,您可以采取下一组操作。
  5. 示例代码:

    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;
                }
            }
        }
    }