您的位置:首页 > 其它

每日之学(2016.04.08)

2016-04-08 21:52 316 查看

线程池

四种线程池

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;


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



改进原理

参考: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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: