Using threads with return values in Java

Keywords: Java

When creating a multithreaded program, we often implement the runnable interface. Runnable does not have a return value. To get the return value, Java 5 provides a new interface Callable, which can get the return value in the thread. However, when getting the return value of the thread, we need to note that our method is asynchronous. When getting the return value, the thread task does not necessarily have a return value, Therefore, it is necessary to judge whether the thread ends before the value can be taken.

Test code

package com.wuwii.test;

import java.util.concurrent.*;

/**
 * @author Zhang Kai
 * @version 1.0
 * @since <pre>2017/10/31 11:17</pre>
 */
public class Test {

    private static final Integer SLEEP_MILLS = 3000;

    private static final Integer RUN_SLEEP_MILLS = 1000;

    private int afterSeconds = SLEEP_MILLS / RUN_SLEEP_MILLS;

    // Thread pool (based on the number of cores on the machine)
    private final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    private void testCallable() throws InterruptedException {
        Future<String> future = null;
        try {
            /**
             * When creating multithreaded programs, we often implement the runnable interface. Runnable has no return value. To get the return value, Java 5 provides a new interface called able
             *
             * Callable You need to implement the call() method instead of the run() method. The return value type is specified by the Callable type parameter,
             * Callable It can only be executed by ExecutorService.submit(), and a future object will be returned after normal completion.
             */
            future = fixedThreadPool.submit(() -> {
                Thread.sleep(SLEEP_MILLS);
                return "The thread returns value.";
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (future == null) return;

        for (;;) {
            /**
             * Before getting the future object, you can use the isDone() method to check whether the future is complete. After that, you can call the get() method to get the value of the future,
             * If you call the get() method directly, the get() method will block until the end of the thread, which is wasteful.
             */
            if (future.isDone()) {
                try {
                    System.out.println(future.get());
                    break;
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("After " + afterSeconds-- + " seconds,get the future returns value.");
                Thread.sleep(1000);
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        new Test().testCallable();
    }
}

Operation result:

After 3 seconds,get the future returns value.
After 2 seconds,get the future returns value.
After 1 seconds,get the future returns value.
The thread returns value.

Conclusion:

  1. The thread that needs to return the value uses the Callable interface to implement the call method;
  2. Before getting the future object, you can use the isDone() method to check whether the future is complete. After that, you can call the get() method to get the value of the future. If you call the get() method directly, the get() method will block until the end of the thread.

Posted by paulintodarkness on Thu, 26 Mar 2020 07:52:39 -0700