【线程】Java让线程执行也具有返回值

Thread线程的run方法是没有返回值的。

 /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

Thread的成员变量是一个线程链接类:实现了Runnable接口的对象,这个对象的run方法也是没有返回值的。

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

传统的使用new Thread(Runnable r).start()的启动Runnable的方式直接调用的是Runnable的run方法,这种是没有返回值的。

如何让线程返回执行结果呢,比如返回一个布尔值true

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

有两种方法。

第一种方法:使用线程池来提交调用Runnable。

    @Test
    public void test() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future demoFuture2 = executorService.submit(new DemoRunnable(1),"123456");
        try {
            System.out.println(demoFuture2.get());
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

Executors.newCachedThreadPool()这里返回了一个线程池,executorService.submit调用了一个Runnable并且返回一个异步计算结果Future,参数“123456”是Future执行get方法(阻塞了当前线程)得到的返回值。如果我们不传入参数“123456”,即

        Future demoFuture2 = executorService.submit(new DemoRunnable(1));

返回值是null,因为默认是没有返回值的。

这种方法非常只能勉强返回一个固定的值,不是我们预期的功能。难道Java这么弱鸡真的没有其他办法了吗?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

有的。

第二种方法:使用Callable来代替Runnable。

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}
    @Test
    public void test() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Boolean> demoFuture = executorService.submit(new DemoCallable(1));
        try {
            System.out.println(demoFuture.get());
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }


// 一个Callable的Demo
class DemoCallable implements Callable<Boolean> {
    private Integer id;
    public DemoCallable(int id) {
        Thread.currentThread().setName(Thread.currentThread().getName() + id);
        this.id = id;
    }
    @Override
    public Boolean call() throws Exception {
        for (int i = 0; i < 30 ; i++) {
            Thread.sleep(1000);
            System.out.println(i + ":" + Thread.currentThread().getName());
        }
        return true;
    }
}

单元测试运行结果:

【线程】Java让线程执行也具有返回值

可以看到,第二种方法更加灵活,而且支持抛出异常。