Future模式:
其实相当于是前端的Ajax
比如我们使用多线程下载文件时候,每一个线程都会发送HTTP请求资源。而我如何知道,文件下载完毕呢?
也就是说,主线程如何获得子线程的执行结果呢?
创建多线程中的实现runnable接口方式和继承thread类,然后start方法都是直接执行代码的,无法知道执行的结果(主线程无法知道进度)。
这里要说的是新方式:使用Callable接口和Future模式
public class CallableTest { public static void main(String[] args) throws Exception { ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); Future<String> submit = newCachedThreadPool.submit(new TaskCallable()); System.out.println("主线程运行"); String result = submit.get(); System.out.println(result); } } class TaskCallable implements Callable { @Override public String call() throws Exception { System.out.println("开始执行任务"); Thread.sleep(3000); System.out.println("执行任务结束"); return "success"; } }
打印:
主线程运行
开始执行任务
执行任务结束
success
Future模式核心:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑
Future模式实例:对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等到B有结果时再取真实的结果
自己实现Future模式:
/** * 公共Data数据结果 */ public abstract class Data { /** * 返回线程的执行结果 * @return String */ public abstract String getRequest(); }
/** * 获取真实数据 */ public class RealData extends Data { private String result; RealData(String data) { System.out.println("正在使用data->" + data + " 进行网络请求"); try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } System.out.println("操作执行完毕"); this.result = "success"; } @Override public String getRequest() { return result; } }
/** * 当有线程要获取RealData的时候 * 程序会被阻塞 * 等到RealData被注入才会使用getRequest方法 */ public class FutureData extends Data { private boolean FLAG = false; private RealData realData; /** * 读取Data数据 */ public synchronized void setRealData(RealData realData) { //如果获取到数据直接返回 if (FLAG) { return; } //如果没有获取到数据 this.realData = realData; FLAG = true; notify(); } @Override public synchronized String getRequest() { while (!FLAG) { try { wait(); } catch (Exception e) { e.printStackTrace(); } } return realData.getRequest(); } }
public class FutureClient { public Data submit(String requestData){ FutureData futureData = new FutureData(); new Thread(new Runnable() { @Override public void run() { RealData realData = new RealData(requestData); futureData.setRealData(realData); } }).start(); return futureData; } }
测试类:
public class Main { public static void main(String[] args) { FutureClient futureClient = new FutureClient(); Data request = futureClient.submit("666"); System.out.println("主线程数据发送成功"); System.out.println("主线程执行其他任务"); String result = request.getRequest(); System.out.println(result); } }
打印如下:
主线程数据发送成功 主线程执行其他任务 正在使用data->666 进行网络请求 操作执行完毕 success