每日之学(2016.04.08)

来源:互联网 发布:西方记者知乎 编辑:程序博客网 时间:2024/05/20 21:48

线程池

四种线程池

newCachedThreadPool 无限大小的线程池
newFixedThreadPool 固定大小的线程池
newScheduledPool 周期性执行的线程池
newSingleThreadExecutor 单线程执行线程池,按照FIFO执行
具体而言是Executors类提供的四种静态方法

public static ExecutorService newCachedThreadPool() {    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                  60L, TimeUnit.SECONDS,                                  new SynchronousQueue<Runnable>());}public static ExecutorService newFixedThreadPool(int nThreads) {    return new ThreadPoolExecutor(nThreads, nThreads,                                  0L, TimeUnit.MILLISECONDS,                                  new LinkedBlockingQueue<Runnable>());}public static ExecutorService newSingleThreadExecutor() {    return new FinalizableDelegatedExecutorService        (new ThreadPoolExecutor(1, 1,                                0L, TimeUnit.MILLISECONDS,                                new LinkedBlockingQueue<Runnable>()));} public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {        return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) {        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,              new DelayedWorkQueue()); }

线程池四种状态

当创建线程池后,初始时,线程池处于RUNNING状态;
如果调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不能够接受新的任务,它会等待所有任务执行完毕;
如果调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务;
当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态。

四大组成部分

线程池管理器,管理线程池里面线程创建,执行,销毁
工作线程,执行任务
任务
任务队列

队列参考BlockingQueue

拒绝策略

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

Volley框架原理

基本思想

CacheDispatcher
NetworkDispatcher

private final PriorityBlockingQueue<Request<?>> mCacheQueue =        new PriorityBlockingQueue<Request<?>>();private final PriorityBlockingQueue<Request<?>> mNetworkQueue =        new PriorityBlockingQueue<Request<?>>();private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;private NetworkDispatcher[] mDispatchers;private CacheDispatcher mCacheDispatcher;

将请求任务加入到请求队列中去,先从缓存队列中找,如果存在该请求,那么就获取结果;否则就加入到网络请求队列中去,将请求的结果放入到缓存队列中去。
volley请求原理

改进原理

参考:https://www.zhihu.com/question/24695486
当dispatcher出现 未捕获异常时,当前线程被干掉这一点考虑,如果换成线程池自然是个好想法,但是线程池的考虑本身是为了管理线程频繁创建,避免过多开销的。然而,默认开启4个NetworkDispatcher就一直让他跑着,我觉得用不用线程池到时无所谓啦。然而,其request的确实恶心了我,直接上来就是http相关的 ,那么问题来了,我如果直接使用socket和后台交互呢?所以,个人认为google这个地方设计还不够上层,这个地方写的太low了。

那么既然提到使用线程池,我也尝试这试了一试
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(mDispatchers.length);

    // Create network dispatchers (and corresponding threads) up to the pool size.    for (int i = 0; i < mDispatchers.length; i++) {        NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,                mCache, mDelivery);        mDispatchers[i] = networkDispatcher;        threadPoolExecutor.submit(networkDispatcher);        //networkDispatcher.start();    }

作者:张哥
链接:https://www.zhihu.com/question/24695486/answer/75615773
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

BlockingQueue

常见方法

插入元素, add offer put
移除元素, remove poll take
其中put和take是阻塞的方法

BlockingQueue的五个常见具体的实现类

ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小。其所含的对象是以FIFO(先入先出)顺序排序的。
LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定。其所含的对象是以FIFO顺序排序的。
PriorityBlockingQueue:类似于LinkedBlockingQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数所带的Comparator决定的顺序。
SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的。 一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。在线程池中应用中,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
DelayQueue:Delayed 元素的一个无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部 是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且 poll 将返回 null。当一个元素的getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满。此队列不允许使用 null 元素。

二叉查找树

实现了基本的二叉查找树

实现了插入和删除操作。
这里发现了一个很有意思的操作,之前写二叉查找树的时候,总是要寻找它的父节点,很不方便。而这里采用的返回节点的方式,自动将操作变化后的节点挂靠在父节点下面。
代码在:https://github.com/lincolnmi/algorithms/tree/master/src/Search/BinarySearchTree

红黑树

这里发现了一个之前未发现的知识,将红黑树类比为2-3树,红颜色代表的是父节点指向子节点的链的颜色,并意味着2-3树的3-节点,只是将节点拆分了。
实现了红黑树的插入操作
代码在:https://github.com/lincolnmi/algorithms/tree/master/src/Search/RBTree

无序数组中寻找第K大的数

借鉴类似快排的思想,对原数组进行分割
核心代码:

 private T select(T[] array,int k,int left,int right) {        int j = partition(array,left,right);        if (j<k) {            return select(array,k,j+1,right);        } else if (j>k) {            return select(array,k,left,j-1);        } else {            return array[j];        }    }

所有代码在:https://github.com/lincolnmi/algorithms/tree/master/src/Search/FindKthElement

0 0
原创粉丝点击