Java并发——Future和Callable

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");
    }
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值