0
点赞
收藏
分享

微信扫一扫

FutureTask的理解(附代码示例)

言午栩 2022-04-25 阅读 43
java

FutureTask的概念

        Future接口定义了操作异步任务执行一些方法,如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等。

        比如主线程让一个子线程去执行任务,子线程可能比较耗时,启动子线程开始执行任务后,主线程就去做其他事情了,过了一会才去获取子任务的执行结果

FutureTask的缺点

get()容易导致阻塞 :只要出现get方法,不管是否计算完成都阻塞等待结果出来再运行

解决办法:用轮询(CAS)替代阻塞

(但是轮询也不见得好,轮询的方式会耗费无谓的CPU资源,而且也不见得能及时地得到计算结果。)

代码示例

通过FutureTask定义一个子线程futureTask,在主线程t1中调用。

这样t1可以将一些费时的事情交给子线程处理,t1然后继续执行,最后子线程再将处理结果返回给主线程。

例子

(以老师上课为例,老师(主线程t1)上课突然口渴了,如果他停止授课,自己去接水(费时的事情),同学们的上课体验就不会太好。如果他喊班长(子线程futureTask)帮他去接水,自己继续授课,同学们的上课体验就是连贯的。最后老师也拿到了班长接的水(处理结果)

public class FutureTaskDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        //定义一个子线程
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
            //暂停几秒线程
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1024;
        });
    
        new Thread(futureTask,"t1").start();
        //获取子线程的结果,推荐放在最后
        System.out.println(futureTask.get()); //不见不散,只要出现get方法,不管是否计算完成都阻塞等待结果出来再运行
    }
}

 

get()阻塞

只要出现get方法,不管是否计算完成都阻塞等待结果出来再运行。

此时,出现get方法,但是因无法获取返回值,导致阻塞。

public class FutureTaskDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        //定义一个子线程
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
            //暂停几秒线程
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1024;
        });

        System.out.println(futureTask.get());
        new Thread(futureTask,"t1").start();
     
    }
}

get:过时不后,只等待设定的时间

设置指定时间,当在规定时间内,子线程仍未得到结果,就报错java.util.concurrent.TimeoutException

public class FutureTaskDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        //定义一个子线程
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
            //暂停几秒线程
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1024;
        });
        new Thread(futureTask,"t1").start();
        System.out.println(futureTask.get(2L,TimeUnit.SECONDS));//过时不后,只等待设定的时间
    }
}

 isDone()轮询

 用轮询(CAS)替代阻塞

public class FutureTaskDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        //定义一个子线程
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
            //暂停几秒线程
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1024;
        });
        new Thread(futureTask,"t1").start();
        //不要阻塞,尽量使用轮询替代阻塞
        while (true){
            if(futureTask.isDone()){
                System.out.println("---result: "+futureTask.get());
                break;
            }else {
                System.out.println("还在计算中");
            }
        }
    }
}

 

举报

相关推荐

0 条评论