我是靠谱客的博主 魁梧烧鹅,最近开发中收集的这篇文章主要介绍Callable的使用和自定义自己的Callable接口,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Callable对比Runnale接口来说,可以返回线程执行的结果:

public static void main(String[] args) throws Exception {

        FutureTask future = new FutureTask(() -> {
            TimeUnit.SECONDS.sleep(10);
            return "hello";
        });

        new Thread(future).start();

        // System.out.println(future.get()); 一直阻塞
    
        // timeout会抛出异常 java.util.concurrent.TimeoutException
        System.out.println(future.get(9,TimeUnit.SECONDS)); 
    }

 其实Callable的功能就是通过Runnable接口来实现:

定义自己的Callable接口:

public interface MyCallable<T> {

    T call();
}

定义相应的Future类:

public class MyFuture<T> implements Runnable {

    // volatile保证各线程内存的可见性,一定要加上
    // 不然 get()方法可能会一直阻塞没有结果返回
    private volatile Object result; 
    private MyCallable<T> myCallable;

    public MyFuture(MyCallable<T> myCallable) {
        this.myCallable = myCallable;
    }

    @Override
    public void run() {
       // 调用call的方法
       Object tempResult = myCallable.call();
       // 将call方法返回的结果,给到result成员变量
       result = tempResult;
    }

    // 阻塞方法,一直阻塞,直到拿到结果
    public Object get(){
        // 结果没有返回,一直阻塞(这里会一直耗用cpu的资源)
        while (result == null);
        return result;
    }

    // 限时阻塞,在一定时间内阻塞,timeout后返回null
    public Object get(long delta, TemporalUnit timeUnit){
        LocalDateTime localDateTime = LocalDateTime.now().plus(delta,timeUnit);
        // 结果没有返回会阻塞delta时间,单位为timeUnit,如果result有值就返回,
        // 没有,那么达到预定时间会返回null,不会一直阻塞,你也可以抛出相应的异常
        while (result == null && localDateTime.compareTo(LocalDateTime.now()) >= 0);
        return result;
    }
}

测试:

public class Test {

    public static void main(String[] args) {
        // 这里用到了java8的lamda表达式重写call方法
        MyFuture<String> myFutrue = new MyFuture<>(()->{
            try {
                // 模拟业务操作,睡3秒
                TimeUnit.SECONDS.sleep(3);
            }catch (Exception e){

            }
            return "hello";
        });
        new Thread(myFutrue).start();

        // System.out.println(myFutrue.get()); 阻塞三秒后返回hello
        // System.out.println(myFutrue.get(2, ChronoUnit.SECONDS)); 阻塞两秒后,返回null
        System.out.println(myFutrue.get(4, ChronoUnit.SECONDS));// 阻塞3秒后返回hello
    }
}

jdk里面的Callable实现可能更完善些,这些都是我随便想的,实现方式很多种,看你怎么实现。感觉这里用阻塞队列来实现应该也是可以的。就是call方法返回的值进入到队列种,get方法可以提供各种场景的返回值或者抛出异常,都可以用阻塞队列来完成。

最后

以上就是魁梧烧鹅为你收集整理的Callable的使用和自定义自己的Callable接口的全部内容,希望文章能够帮你解决Callable的使用和自定义自己的Callable接口所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(77)

评论列表共有 0 条评论

立即
投稿
返回
顶部