总是套路留人心, JAVA提供的套路: LinkedHashMap实现LRU缓存; InvocationHandler实现动态代理; fork/join实现窃取算法

1. LinkedHashMap实现LRU缓存

LRU缓存核心是根据访问顺序排序, 自动移除队尾缓存, LinkedHashMap已经实现了这些要求:

public LRUCache<K, V> extends LinkedHashMap<K, V> {
    private int cacheSize;
    
    public LRUCache(int cacheSize){
        super(16, 0.75, true);   // key1: true表示使用访问排序, 默认false表示插入排序 
}
    @Override
    protected boolean removeEldestEntry(Map.Entry<k, V> eldest){
        return size() >= cacheSize;  //key2: 每次调用add后, 底层都会调用这个方法判断是否执行移除队尾元素, 通过重写这个方法来控制移除时机
}
}

2.InvocationHandler实现动态代理

手工为每一个类实现一个代理类称为静态代理, 缺点是即使代理的操作是一样的, 仍然要为每个类实现一个代理类, 代理操作代码不能复用

//1.实现代理类
public class MyInvocationHandler implements InvocationHandler {  
    private Object target;  
  
    MyInvocationHandler() {  
        super();  
    }  
  
    MyInvocationHandler(Object target) {  
        super();  
        this.target = target;  
    }  
  
    @Override  
    public Object invoke(Object o, Method method, Object[] args) throws Throwable {  
        if("getName".equals(method.getName())){  
            System.out.println("++++++before " + method.getName() + "++++++");  
            Object result = method.invoke(target, args);  
            System.out.println("++++++after " + method.getName() + "++++++");  
            return result;  
        }else{  
            Object result = method.invoke(target, args);  
            return result;  
        }  
    }  

//2.获得代理对象
(TargetInterface)Proxy.newProxyInstance(tarInterClass.getClassLoader(), tarInterClass.getInterface(), new MyInvocationHandler(tarObj));

可以看出Proxy.newProxyInstance()获得的是对一个接口的代理, 这也是InvocationHandler动态代理的缺点:只能代理接口中的方法.

想代理类中非implement接口的方法, 可以用第三方Cglib代理实现

3.fork/join实现窃取模式

窃取模式是一种升级版的生产者-消费者模式, 特点是线程在处理完自己的任务队列后, 回去其他线程的任务队列的末尾窃取任务来执行, 以提高效率.

如果自己实现窃取模式:首先要一个线程池来执行任务, 其次要为每一个线程提供一个任务队列, 最后还要实现窃取其他队列的任务的功能. 幸运的是JAVA已经提供了实现.

//1.编写任务类implement
RecursiveAction    不反回结果, 相当于Runnable
RecursiveTask        返回结果, 相当于Callable
//2.获得线程池
ForkJoinPool pool = new ForkJoinPool()
//3.提交任务
    pool.execute()    异步执行命令
    pool.invoke()    执行命令并直接返回结果
    pool.submit()   执行任务并返回一个ForkJoinTask(Future)
//4.子RecusiveAction
    fork()    //把自身添加到任务执行队列
    join()    //获得执行结果

在compute()的实现中, 根据条件将任务分成更细的多个RecusiveTask, 就实现了分治法  

  

posted @ 2017-03-15 23:18  长乐忘忧  阅读(384)  评论(0编辑  收藏  举报