FutureTask使用,核心原理解析

1. FutureTask的用法

在Java中,一般是通过继承Thread类或者实现Runnable接口来创建多线程,Runnable接口不能返回结果,如果要获取子线程的执行结果,一般都是在子线程执行结束之后,通过Handler将结果返回到调用线程,jdk1.5之后,Java提供了Callable接口来封装子任务,Callable接口可以获取返回结果。

FutureTask + Thread 

public class Test {

    public static void main(String[] args) {

        FutureTask<Integer> firstTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 1;
            }
        });
        FutureTask<Integer> secondTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 2;
            }
        });
        // FutureTask有Runnable接口和Callable接口的特征,可以被Thread执行。
        new Thread(firstTask).start();
        new Thread(secondTask).start();
        try {
            Integer one = firstTask.get();
            Integer two = secondTask.get();
            System.out.println(one); // 1
            System.out.println(two);// 2
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

    Future + ExecutorService

public class Test {

    public static void main(String[] args) {

        FutureTask<Integer> firstTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 1;
            }
        });
        FutureTask<Integer> secondTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 2;
            }
        });

        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(firstTask);
        executorService.submit(secondTask);
        executorService.shutdown();
        try {
            Integer one = firstTask.get();
            Integer two = secondTask.get();
            System.out.println(one); // 1
            System.out.println(two);// 2
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
2.仿造futuretask核心原理,实现替换
package com.gpdi.operatingunit.test;

import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.LockSupport;

/**
 * @description: 仿造futuretask核心原理,实现替换
 * @author: Lxq
 * @date: 2020/1/8 9:24
 */
public class DnFutureTask<T> implements Runnable {

    // 线程集合
    LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();

    /**
     * 封装业务逻辑的callable对象
     */
    private Callable<T> callable;

    /**
     * 返回值
     */
    T call;
    String state = "new";

    public DnFutureTask(Callable<T> callable) {
        this.callable = callable;
    }

    /**
     * 执行业务逻辑
     */
    @Override
    public void run() {
        try {
            call = callable.call();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            state = "end";
        }

        while (true) {
            Thread waiter = waiters.poll();
            if (waiter == null) {
                break;
            }
            LockSupport.unpark(waiter);
        }
    }



    /**
     * 获取执行结果
     */
    public T get() {
        Thread mainThread = Thread.currentThread();
        waiters.add(mainThread);
        // 判断是否执行完毕,如果执行完毕,则让当前调用get的方法的线程停一下,等待结果
        if ("end".equals(state)) {
            return call;
        }
        // 等待run执行结果
        System.out.println(Thread.currentThread().getName() + "消费者即进入等待");
        // park unpark 机制,挂起等待
        LockSupport.park(mainThread);

        return call;
    }

}

测试:

public class Test {

    public static void main(String[] args) {

        DnFutureTask<Integer> firstTask = new DnFutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 1;
            }
        });
        DnFutureTask<Integer> secondTask = new DnFutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 2;
            }
        });

        new Thread(firstTask).start();
        new Thread(secondTask).start();
        try {
            Integer one = firstTask.get();
            Integer two = secondTask.get();
            System.out.println(one); // 1
            System.out.println(two);// 2
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

发布了35 篇原创文章 · 获赞 22 · 访问量 978

猜你喜欢

转载自blog.csdn.net/weixin_38982591/article/details/103899696