java异步回调历程

java I/O的经历了BIO(Blocking IO),NIO(Non-blocking IO),AIO(Async-I/O),这些IO技术的发展都是依托已java版本的更新。
本文主要研究一下java的异步回调机制,
主要针对juc包下的Future,Callable,FutureTask,更多关于java I/O历程


**业务场景 **
假定我们有这样一个业务场景,烧一壶开水,烧一壶开水有如下几个步骤:

  1. 加水
  2. 打开煤气
  3. 烧水ing—(比较耗时的动作)
  4. 观察,烧水完成
  5. 最后水开之后,关闭煤气

AbstractBoilWater

public abstract class AbstractBoilWater {
	protected volatile boolean isReadyFlag = false;
	
	protected void a_addWater() {
		System.out.println("1.加水");
	}
	
	protected void b_on() {
		System.out.println("2.打开煤气");
	}
	
	protected void c_boiling() throws Exception {
		System.out.println("3-1.烧水中.....");
		Thread.sleep(5000); //模拟烧水的过程,比较耗时
		System.out.println("3-2.水开了");
		isReadyFlag = true;
	}
	
	protected void d_off() {
		System.out.println("4.关闭煤气");
	}
	
	//烧水方法
	public abstract void make() throws Exception;
	
	protected void playGame() throws Exception {
		Thread.sleep(1200);
		if (!isReadyFlag) {
			System.out.println("水还没烧开,玩一把游戏");
		}
	}
	
}

编写一个抽象类AbstractBoilWater,
其中c_boiling()模拟一个烧水的过程,比较耗时;
提供一个抽象方法make(),各个子类通过重写该方法,用自己的方式来花式烧水


方法一:同步等待
方法一的实现步骤如下:

  • a.加入适量的水
  • b.打开煤气
  • c.暗中观察,等待水烧开 —同步阻塞等待
  • d.关闭煤气

代码一

public class BioBoilWater extends AbstractBoilWater{
	@Override
	public void make() throws Exception {
		a_addWater();
		b_on();
		c_boiling();//同步阻塞等待
		d_off();
	}
}

,由代码可见在烧水的过程中,一直在同步阻塞等待,烧水的这一段时间就白白浪费了。


方法二:Future,Callable-异步执行,同步回调

  • a.加入适量的水
  • b.打开煤气 — 老鸟有一定的经验,目测20分钟之后可以烧开,
  • c.playGame// 打一局小游戏
  • d.观察水是否烧开烧开
  • e.关闭煤气

方法二代码

public class NioBoilWater extends AbstractBoilWater{
	@Override
	public void make() throws Exception {
		ExecutorService executor = Executors.newCachedThreadPool();
		a_addWater();
		b_on();
		Future<Integer> future = executor.submit(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				c_boiling();
				return 1;
			}
		});
		executor.shutdown();
		while(!future.isDone()){
			playGame();//烧水过程中,玩一局游戏
		}
		int a = future.get(); //同步阻塞等待
		d_off();
	}
}

启动一个新的线程去执行c_boiling(),执行过程中,无需同步的阻塞等待,可以去做一些其他一些有意思的事,打游戏playGame(); 最终使用future.get(),这是一个同步阻塞的操作,等待Callable事件完成。
这里注意的一点:Future只能用线程池去调用执行。
Future源码解析

public interface Future<V> {

    //终止当前任务
    boolean cancel(boolean mayInterruptIfRunning);

    //Returns {@code true} if this task was cancelled before it completed
    boolean isCancelled();

   //正常完成,异常,cancel;
    boolean isDone();

	 /**
     * Waits if necessary for the computation to complete, and then
     * retrieves its result.
     *
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     */
    V get() throws InterruptedException, ExecutionException;

    //阻塞--最大等待时间
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}


方法三:FutureTask-异步执行,异步回调

  • a.加入适量的水
  • b.打开煤气
  • c.playGame // 打一局小游戏
  • d.主动提醒,水已烧开 ---- //主动通知-回调
  • e.关闭煤气

方法三代码

public class AioBoilWater extends AbstractBoilWater {
	@Override
	public void make() throws Exception {
		a_addWater();
		b_on();
		FutureTask<Integer> futureTask = new FutureTask(() -> {
			c_boiling();
			return 1;
		}){
			//当futureTask执行完之后,调用done()
			@Override
			protected void done() {
				d_off();
			}
		};
	
		new Thread(futureTask).start();
		while(!futureTask.isDone()){
			playGame();
		}
//		futureTask.get();//阻塞,
		Thread.sleep(5000);
	}
}

FutureTask源码分析
这里写图片描述
,FutureTask实现了Future和Runnable接口, 它可以不适用线程池,直接通过线程启动。
它最大的特点是,它有一个done()回调函数,当前任务状态为isDone时,触发。

  protected void done() {}
   

方法四:CompletableFuture-异步执行,异步回调
使用jdk8新特性:CompletableFuture

public class CompletableFutureBiolWater extends AbstractBoilWater {
	@Override
	public void make() throws Exception {
		a_addWater();
		b_on();
		CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
			try {
				c_boiling();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return 1;
		});
		
		//注册事件“监听”
		future.whenComplete((v, e) -> {
		/*	System.out.println(v);
			System.out.println(e);*/
			d_off();
		});
		
		while (!future.isDone()) {
			playGame();
		}
	}
}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值