【线程】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;
}
}
单元测试运行结果:
可以看到,第二种方法更加灵活,而且支持抛出异常。