在前面一篇文章中,我们简单介绍了java语言中,如何创建线程,使用线程,其中也提到了 Callable的使用,这里单独介绍下 Callable这个接口 看看他的定义:
@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;
}
和Runnable接口类似,也是一个函数式接口,这样我们可以通过lambda表达式进行使用。
Callable接口的特点:提供了方法返回值,这样在线程执行完后,可以获取到相应的返回值。
我们先看看怎么使用:一是可以作为FutureTask的参数,传入到FutureTask对象中,作为任务执行。二是依赖线程池Executor,作为task丢入到线程池中作为独立任务执行。
Talk is cheap,show me your code!!
public class CallableDemo {
static ExecutorService executorService = Executors.newSingleThreadExecutor();
public static void main(String[] args) throws Exception {
callableDemo();
}
private static void callableDemo() throws Exception {
Callable<Long> callable = new Callable<Long>() {
@Override
public Long call() throws Exception {
MyLog.printTimeAndThread("callable");
Thread.sleep(2500);
return 100L; //Thread.currentThread().getId();
}
};
// 1. Callable 对象作为FutureTask对象的参数,在FutureTask中中执行
FutureTask<Long> futureTask = new FutureTask<Long>(callable);
Thread thread = new Thread(futureTask);
thread.start();
Long result = futureTask.get();
System.out.println("futureTask callable result: " + result);
System.out.println("===========================");
// 2. Callable 对象丢入到Executor 线程池中执行
Future<Long> future = executorService.submit(callable);
Long result2 = future.get();
System.out.println("executorService callable result: " + result2);
executorService.shutdown();
}
}
public class MyLog {
public static void sleepMillis(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void printTimeAndThread(String tag) {
String result = new StringJoiner("\t|\t")
.add(String.valueOf(System.currentTimeMillis()))
.add(String.valueOf(Thread.currentThread().getId()))
.add(Thread.currentThread().getName())
.add(tag)
.toString();
System.out.println(result);
}
}
运行结果:
1619072927241 | 12 | Thread-0 | callable
futureTask callable result: 100
===========================
1619072929742 | 13 | pool-1-thread-1 | callable
executorService callable result: 100
这个结果很好理解,我相信,就不多解释了。
把上面的代码这样改下:
private static void callableDemo() throws Exception {
Callable<Long> callable = new Callable<Long>() {
@Override
public Long call() throws Exception {
MyLog.printTimeAndThread("callable");
Thread.sleep(2500);
return 100L; //Thread.currentThread().getId();
}
};
// 1. Callable 对象作为FutureTask对象的参数,在FutureTask中中执行
FutureTask<Long> futureTask = new FutureTask<Long>(callable);
Thread thread = new Thread(futureTask);
thread.start();
Long result = futureTask.get();
System.out.println("futureTask callable result: " + result);
System.out.println("===========================");
// 2. Callable 对象丢入到Executor 线程池中执行
Future<Long> future = executorService.submit(callable);
Long result2 = future.get();
Long result3 = callable.call(); // 多加了这2行代码
System.out.println("result3: " + result3); // 多加了这2行代码
System.out.println("executorService callable result: " + result2);
executorService.shutdown();
}
执行的结果:
1619073040316 | 12 | Thread-0 | callable
futureTask callable result: 100
===========================
1619073042818 | 13 | pool-1-thread-1 | callable
1619073045318 | 1 | main | callable
result3: 100
executorService callable result: 100
可以看出 callable对象执行了两次,相当于这个任务重复执行了两次,一次是在executor线程池中执行的,一次是在main线程执行的。