Future接口的优缺点
优点
future+线程池异步多线程任务配合,能显著提高程序的执行效率。
case:
public class FutureThreadPoolDemo { public static void main(String[] args) throws ExecutionException, InterruptedException { //3个任务,目前只有一个线程main来处理,耗时多少? ExecutorService threadPool = Executors.newFixedThreadPool(3); long startTime = System.currentTimeMillis(); FutureTask<String> task1 = new FutureTask<String>(()->{ try{ TimeUnit.MILLISECONDS.sleep(500);}catch(InterruptedException e) {e.printStackTrace();} return "task1 over"; }); threadPool.submit(task1); FutureTask<String> task2 = new FutureTask<String>(()->{ try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();} return "task2 over"; }); threadPool.submit(task2); System.out.println(task1.get()); System.out.println(task2.get()); try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();} threadPool.shutdown(); //关闭线程池 long endTime = System.currentTimeMillis(); System.out.println("----costTime:"+(endTime-startTime)+"毫秒"); System.out.println(Thread.currentThread().getName()+"\t-------end"); } // private static void m1() { // //3个任务,目前只有一个线程main来处理,耗时多少? // long startTime = System.currentTimeMillis(); // try{ TimeUnit.MILLISECONDS.sleep(500);}catch(InterruptedException e) {e.printStackTrace();} // try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();} // try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();} // long endTime = System.currentTimeMillis(); // System.out.println("----costTime:"+(endTime-startTime)+"毫秒"); // System.out.println(Thread.currentThread().getName()+"\t-------end"); // } }
缺点
- get()方法容易引起阻塞,如果没有计算完成,容易导致程序阻塞。如下程序:
/** * @author ygf * @date 2022/9/18 15:31 * 1.get容易导致阻塞,一般建议放到程序后面,一旦调用不见不散,非要等到结果才会离开,不管计算是否完成,容易引起阻塞。 * 2.假如我不愿意等待很长时间,我希望可以过时不候,到时间了可以自动离开用:task1.get(3,TimeUnit.SECONDS) */ public class FutureAPIDemo { public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { FutureTask<String> task1 = new FutureTask<String>(()->{ try{ TimeUnit.MILLISECONDS.sleep(5000);}catch(InterruptedException e) {e.printStackTrace();} return "task1 over"; }); Thread t1 = new Thread(task1,"t1"); t1.start(); // System.out.println(task1.get()); //调用get(),就会阻塞,不见不散,非要等到结果才会离开 System.out.println(task1.get(3,TimeUnit.SECONDS)); System.out.println(Thread.currentThread().getName()+"----忙其他任务了"); } }
- isDone()轮询 容易引起cpu空转,耗费更多的资源
public class FutureAPIDemo { public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException { FutureTask<String> task1 = new FutureTask<String>(()->{ try{ TimeUnit.MILLISECONDS.sleep(5000);}catch(InterruptedException e) {e.printStackTrace();} return "task1 over"; }); Thread t1 = new Thread(task1,"t1"); t1.start(); // System.out.println(task1.get()); //调用get(),就会阻塞,不见不散,非要等到结果才会离开 // System.out.println(task1.get(3,TimeUnit.SECONDS)); System.out.println(Thread.currentThread().getName()+"----忙其他任务了"); // System.out.println(task1.get()); while (true){ if(task1.isDone()){ System.out.println(task1.get()); break; }else{ try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();} System.out.println("正在处理中......."); } } } }
返回结果
总结
Future对于结果的获取不是很友好,这就是CompletableFuture的诞生的理由了。