十九、JAVA多线程笔记:Future设计模式

Future设计模式是Java多线程开发常用设计模式。

一句话,将客户端请求的处理过程从同步改为异步,以便将客户端解放出来,

在服务端程序处理期间可以去干点其他事情,最后再来取请求的结果。

好处在于整个调用过程中不需要等待,可以充分利用所有的时间片段,提高系统的响应速度。

接口定义

package com.zl.step19;

/**
 * 获取计算呢结果和判断任务是否完成两个接口
 * @param <T>
 */
public interface Future<T> {

    // 返回计算后的结果,该方法会陷入阻塞状态
    T get() throws  InterruptedException ;

    // 判断任务是否已经被完成
    boolean done();

}
package com.zl.step19;

public interface Task<IN,OUT> {
    // 给定一个参数,经过计算返回结果
    OUT get(IN input);
}
package com.zl.step19;

import java.util.concurrent.Callable;

public interface FutureService<IN,OUT> {

    // 接受不需要返回值的任务
    Future<?> submit(Runnable runnable);

    // 提交需要返回值的任务
    Future<OUT> submit(Task<IN,OUT> task, IN input);

    // 提交需要返回值的任务 回调函数
    Future<OUT> submit(Task<IN,OUT> task, IN input, Callback<OUT> callback);


    // 使用静态方法构建一个FutureService
    static <T,R> FutureService<T,R> newService(){
        return new FutureServiceImpl<>();
    }



}
package com.zl.step19;

public interface Callback<T> {
    //任务完成后会调用该方法, 其中T为任务执行后的结果
    void call(T t);
}

程序实现

package com.zl.step19;

public class FutureTask<T> implements Future<T> {

    // 计算结果
    private T result ;

    // 是否已经完成
    private boolean isDone = false ;

    // 定义对象锁
    private final Object LOCK = new Object() ;


    @Override
    public T get() throws InterruptedException {
        synchronized (LOCK) {

            // 当任务还没有完成时,调用get方法被挂起,进入阻塞
            while (!isDone) {
                LOCK.wait();
            }

        }
        // 计算返回结果
        return result;
    }

    // 设置计算结果
    protected void finish(T result){
        synchronized (LOCK) {
            if(isDone){
                return;
            }

            this.result = result ;
            this.isDone = true;
            LOCK.notifyAll();

        }

    }

    @Override
    public boolean done() {
        return isDone;
    }
}
 
package com.zl.step19;


import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 * 当提交任务的时候,创建一个信息的线程来受理该任务,进而达到任务异步执行的效果
 * @param <IN>
 * @param <OUT>
 */
public class FutureServiceImpl<IN,OUT> implements FutureService<IN,OUT> {

    // 为执行的线程指定名字前缀
    private final static String FUTURE_THREAD_PREFIX = "FUTURE-" ;

    private final AtomicInteger nextCounter = new AtomicInteger(0) ;

    private String getNextName(){
        return FUTURE_THREAD_PREFIX+nextCounter.getAndIncrement() ;
    }


    @Override
    public Future<?> submit(Runnable runnable) {
        final FutureTask<Void> future = new FutureTask<>();
        new Thread(()->{
            runnable.run();
            future.finish(null);

        },getNextName()).start();
        return future;
    }

    @Override
    public Future<OUT> submit(Task<IN, OUT> task, IN input) {
        final FutureTask<OUT> future = new FutureTask<>();
        new Thread(()->{
            OUT result = task.get(input) ;
            //  设置返回结果
            future.finish(result);

        },getNextName()).start();
        return future;
    }



    @Override
    public Future<OUT> submit(Task<IN, OUT> task, IN input, Callback<OUT> callback) {
        final FutureTask<OUT> future = new FutureTask<>();
        new Thread(()->{
            OUT result = task.get(input) ;
            //  设置返回结果
            future.finish(result);
            if(null != callback){
                //  回调函数
                callback.call(result);
            }

        },getNextName()).start();
        return future;
    }


}

使用&总结

package com.zl.step19;

import java.util.concurrent.TimeUnit;

// 提交无返回值的任务
public class FutureTest01 {
    public static void main(String[] args) throws InterruptedException {
        FutureService<Void,Void> service = FutureService.newService();

       Future<?> future = service.submit(()-> {
           try {
               TimeUnit.SECONDS.sleep(5);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           System.out.println("I am finish done .");

       });
        //get 方法 会使当前线程进入
        future.get();

    }

}
package com.zl.step19;

import java.util.concurrent.TimeUnit;

// 提交有返回值的任务
public class FutureTest02 {
    public static void main(String[] args) throws InterruptedException {
        FutureService<String,Integer> service = FutureService.newService();

       Future<Integer> future = service.submit(input-> {
           try {
               TimeUnit.SECONDS.sleep(5);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           return input.length();

       },"Hello");
        //get 方法 会使当前线程进入
        future.get();

    }

}
package com.zl.step19;

import java.util.concurrent.TimeUnit;

// 提交有返回值的任务 支持回调函数
public class FutureTest03 {
    public static void main(String[] args) throws InterruptedException {
        FutureService<String,Integer> service = FutureService.newService();

       Future<Integer> future = service.submit(input-> {
           try {
               TimeUnit.SECONDS.sleep(5);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           return input.length();

       },"Hello",System.out::println);
        //get 方法 会使当前线程进入
        future.get();

    }

}

猜你喜欢

转载自blog.csdn.net/zhanglong_4444/article/details/86291665