##阻塞队列
以arrayBlockingQueue为例
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(2000, true);
LinkedBlockingDeque linkedBlockingDeque = new LinkedBlockingDeque(2000);
/**
- 往队列中放入数据
- /
arrayBlockingQueue.offer(new Object());//加入缓存队列,blockingqueue可以容纳返回ture,否则false,不阻塞当前线程
try {
//加入缓存队列,设置超时时间
arrayBlockingQueue.offer(new Object(), 5, TimeUnit.SECONDS);
//加入缓存队列,如果队列没有空间,调用方法的线程被阻塞,直到队列里有控件再继续
arrayBlockingQueue.put(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
- 从队列中获取数据
- /
try {
//取走队列中排在首位的对象,取不到返回null
arrayBlockingQueue.poll();
//取走队列中排在首位的对象,如果不能立即取出,可以等待超时时间,取不到返回null
arrayBlockingQueue.poll(5, TimeUnit.SECONDS);
//取走队列中的排在首位的对象,若队列为空,则阻断进入等待状态,知道队列有新的数据被加入
arrayBlockingQueue.take();
//一次性从队列中获取所有可用的数据对象,可以加个参数来指定获取的个数,可提升获取数据的效率,无须多次分批加锁或释放锁
arrayBlockingQueue.drainTo(new ArrayList());
} catch (InterruptedException e) {
e.printStackTrace();
}
我目前遇到Android常用的前两个
ArrayListBlockingQueue:数组结构组成的有界阻塞队列
先进先出对元素进行排序
保证公平的访问队列,会降低吞吐量(公平的访问队列也就是:先阻塞的线程生产者线程先插入,先阻塞的消费者线程先拿取队列的元素)
(默认情况下不保证线程公平的访问队列)但是可以配置公平访问队列:
ArrayListBlockingQueue fairQueue = new ArrayListBlockingQueue(2000,true);
LinkedBlockingQueue:链表结构组成的有界队列
先进先出对元素进行排序
内部维持着一个数据缓冲队列(链表组成的队列),生成者放入数据时,队列中缓存,生产者立即返回。
只有当缓冲区达到缓存容量的最大值时(构造时可指定容量),才会阻塞生产者队列,直到消费者从缓存队列消耗掉一份数据时,生产者线程才会被唤醒
PriorityBlockQueue:支持优先级的无界队列
DelayQueue:支持延迟获取元素的无界阻塞队列
SynchronousQueue:不存储元素的阻塞队列
LinkedTransferQueue:由链表组成的无界阻塞TransferQueue队列,实现重要接口TransferQueue,接口的5个方法有3个重要方法,transfer、trytransfer(o)、trytransfer(o,timeout,unit)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
LinkedTransferQueue transferQueue = new LinkedTransferQueue(new LinkedList());
try {
//如果存在正在获取数据的消费者线程,立即传递元素过去,如果没有,则将元素插入队列尾部,进入阻塞等待被消费者拿去数据
transferQueue.transfer(new Object());
//如果存在正在获取数据的消费者线程,立即传递元素过去,如果没有,则立即返回false,
// 不阻塞线程,不管有没有消费者接受数据,都会立即返回
transferQueue.tryTransfer(new Object());
//如果存在正在获取数据的消费者线程,立即传递元素过去,如果没有,在队列尾部插入元素,
// 等待超时时间,未被获取则返回false,被获取返回true
transferQueue.tryTransfer(new Object(), 5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}创建线程池的5种方法:
private void createThreadPool() {
int cpuCount = Runtime.getRuntime().availableProcessors();
int corePoolSize = cpuCount + 1;
int maximumPoolSize = cpuCount * 2 + 1;
int keepAliveTime = 10;
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(128);
ThreadFactory factory = new ThreadFactory() {
private final AtomicInteger mAtomicCount = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "thread-" + mAtomicCount);
}
};
mExecutorService = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,
arrayBlockingQueue,factory,new ThreadPoolExecutor.AbortPolicy());
//确保都是核心线程去执行任务
mExecutorService1 = Executors.newFixedThreadPool(5);
//没有核心线程,每当又任务都是立即转给一般消费线程去执行,所以适合大量立即处理且耗时少的任务
mExecutorService2 = Executors.newCachedThreadPool();
//只有单一的核心线程,保证任务按照添加顺序执行
mExecutorService3 = Executors.newSingleThreadExecutor();
//里面的阻塞队列是DelayedWorkQueue,所以适合执行定时或者周期性的任务
mExecutorService4 = Executors.newScheduledThreadPool(10);
}关于AsyncTask的内容:
内部实现也是通过线程池事项,线程池任务容量有限,核心线程(Math.max(2, Math.min(CPU_COUNT - 1, 4)))+阻塞队列(128)
1 | //串行执行任务,通过SerialExecutor来实现一个任务执行完毕之后才执行下一个 |
- 本文作者: 风追着云
- 本文链接: https:/github.com/tuyrt7/tuyrt7.github.io/2019/10/09/多线程相关/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!

SongTaste