Future和Callable
Callable和Runnable主要区别为:
- Callable接口的call)方法可以有返回值,而Runnable接口的run()方法没有返回值。
- Callable 接口的call0)方法可以声明抛出异常,而Runnable接口的run()方法不可以声明抛出异常。
执行完Callable接口中的任务后,返回值是通过Future 接口进行获得的。
get()和ExecutorService中的submit()和isDone()的使用
方法submit()不仅可以传人Callable对象,也可以传人Runnable对象,说明submit()方法支持有返回值和无返回值的功能。
public class TestDemo {
public static void main(String[] args) {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "返回值";
}
};
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(callable);
System.out.println(future.isDone());
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
get()方法具有阻塞性,而isDone()方法无阻塞性。
cancel(boolean mayInterruptIfRunning)和isCancelled()的使用
- 方法cancel(boolean mayInterruptIfRunning)的参数mayInterruptIfRunning的作用是:如果线程正在运行则是否中断正在运行的线程,在代码中需要使用
if(Thread.currentThreadO.islnterrupted()
进行配合。 - 方法cancel()的返回值代表发送取消任务的命令是否成功完成。
public class TestDemo2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "我的年龄是100";
}
};
ExecutorService executorService = new ThreadPoolExecutor(50, Integer.MAX_VALUE, 5,
TimeUnit.SECONDS, new LinkedBlockingDeque<>());
Future<String> future = executorService.submit(callable);
System.out.println(future.get());
System.out.println(future.cancel(true) + " " + future.isCancelled());
}
}
从打印的结果来看,线程任务已经运行完毕,线程对象已经销毁,所以方法cancel()的返回值是false,代表发送取消的命令并没有成功。
public class TestDemo2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "我的年龄是100";
}
};
ExecutorService executorService = new ThreadPoolExecutor(50, Integer.MAX_VALUE, 5,
TimeUnit.SECONDS, new LinkedBlockingDeque<>());
Future<String> future = executorService.submit(callable);
System.out.println(future.cancel(true) + " " + future.isCancelled());
}
}
任务在没有运行完成之前执行了cancel()方法返回为true,代表成功发送取消的命令。
结合if(Thread.currentThread().isInterrupted())中断线程:
public class TestDemo3 {
public static void main(String[] args) throws InterruptedException {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
int i = 0;
while (i == 0) {
if (Thread.currentThread().isInterrupted())
throw new InterruptedException();
System.out.println("正在运行中");
}
return "返回值";
}
};
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(callable);
Thread.sleep(3000);
System.out.println(future.cancel(true) + " " + future.isCancelled());
}
}
线程中断成功。
如果cacnel()传入false,则线程不中断。
get(long timeout, TimeUnit unit):
方法get(long timeout, TimeUnit unit) 的作用是在指定的最大时间内等待获得返回值。
execute()和submit()的区别
- 方法execute()没有返回值,而submit()方法可以有返回值。
- 方法execute()在默认的情况下异常直接抛出,不能捕获,但可以通过自定义ThreadFactory的方式进行捕获,而submit()方法在默认的情况下,可以try-catch捕获异常。
execute()出现异常后直接打印堆栈信息:
public class TestDemo4 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
Integer.parseInt("xxx");
});
}
}
submit()方法可以捕获异常:
public class TestDemo4 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(() -> {
Integer.parseInt("xxx");
return "返回值";
});
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
System.out.println("能捕获异常");
}
}
}
execute()方法通过ThreadFactory捕获异常:
public class TestDemo5 {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 10, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("executor()方法通过使用自定义");
System.out.println("ThreadFactory也能捕获异常");
e.printStackTrace();
}
});
return t;
}
});
pool.execute(() -> {
Integer.parseInt("xxx");
});
System.out.println("main end");
}
}