该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,若是能给各位看官带来一丝启发或者帮助,那真是极好的。java
上一篇说到了Android并发编程中的 原子类与并发容器,那么本篇呢,继续上一篇记录一下Android并发编程中经常使用的一些工具类,以及面试必问知识点--线程池.面试
CountDownLatch容许一个或多个线程等待其余线程完成操做。编程
当咱们须要用多个线程分解一些比较复杂任务时,这些任务一般符合下面两个规则:多线程
用法:并发
public class CountDownLatchTest { static CountDownLatch c = new CountDownLatch(2); public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() { @Override public void run() { System.out.println(1); c.countDown(); System.out.println(2); c.countDown(); } }).start(); c.await(); System.out.println("3"); } }
CountDownLatch的构造函数接收一个int类型的参数做为计数器,若是你想等待N个点完成,这里就传入N。当咱们调用CountDownLatch的countDown方法时,N就会减1,CountDownLatch的await方法会阻塞当前线程,直到N变成零。框架
除了await()方法以外,也可使用另一个带指定时间的await方法——await(long time,TimeUnit unit),这个方法等待特定时间后,就会再也不阻塞当前线程。异步
总结来讲就是等待多个线程的完成,而后本身(调用await方法的线程)才运行.ide
同步屏障要作的事情是,让一个线程到达一个屏障(也能够叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,全部被屏障拦截的线程才会继续运行。
用法函数
public class CyclicBarrierTest { static CyclicBarrier c = new CyclicBarrier(2); public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { try { c.await(); } catch (Exception e) { } System.out.println(1); } }).start(); try { c.await(); } catch (Exception e) { } System.out.println(2); } }
CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数
量,每一个线程调用await方法告诉CyclicBarrier我已经到达了屏障,而后当前线程被阻塞。当全部线程都到达了屏障时(即都调用了await方法)时,全部线程进行CPU竞争,由CPU调度运行.工具
Semaphore,信号量(令牌数).信号量这个概念跟咱们到一个很是火的饭店排队领号吃饭同样,因为饭店的容量是有限的,只能容纳N我的,前面N我的被叫到号进去用餐,其余的人只能等待,直到饭店中有人离开,才会继续叫号.
Semaphore的构造方法Semaphore(int permits)接受一个整型的数字,表示可用的许可证数量。在上面的例子中这个数字就是饭店中能容纳的人数.正在饭店内用餐的人表明正在运行的线程,在外面的等待的人表明阻塞的线程,吃完饭离开的人表明已经运行完毕的线程.
用法
public class SemaphoreTest { private static final int THREAD_COUNT = 30; private static ExecutorServicethreadPool = Executors .newFixedThreadPool(THREAD_COUNT); private static Semaphore s = new Semaphore(10); public static void main(String[] args) { for (inti = 0; i< THREAD_COUNT; i++) { threadPool.execute(new Runnable() { @Override public void run() { try { s.acquire(); System.out.println("save data"); s.release(); } catch (InterruptedException e) { } } }); } threadPool.shutdown(); } }
在代码中,虽然有30个线程在执行,可是只容许10个并发执行。Semaphore(10)表示容许10个线程获取许可证,也就是最大并发数是10。
Semaphore使用Semaphore的acquire()方法获取一个许可证,使用完以后调用release()方法归还许可证。还能够用tryAcquire()方法尝试获取许可证。
Java中的线程池是运用场景最多的并发框架,几乎全部须要异步或并发执行任务的程序
均可以使用线程池。在开发过程当中,合理地使用线程池可以带来3个好处。
Java中经常使用的线程池都是ThreadPoolExecutor不一样的配置产生的以符合不一样的场景.因此理解ThreadPoolExecutor相当重要.
下图是线程池的原理模型.
有了线程池的原理模型以后,咱们再看在Java库中是如何实现这个模型的,下面咱们来看ThreadPoolExecutor
FixedThreadPool被称为可重用固定线程数的线程池。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
FixedThreadPoolExecutor是一种线程数量固定的线程池,当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭了.当全部的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来.因为FixedThreadPool只有核心线程而且这些核心线程不会被回收,这意味着它可以更加快速的响应外界的请求.
SingleThreadExecutor是使用单个worker线程的Executor.
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
SingleThreadPool内部只有一个核心线程,它确保全部的任务都在同一个线程中按顺序执行.
CachedThreadPool是一个会根据须要建立新线程的线程池。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
CachedThreadPool是一种线程数量不定的线程池,它只有非核心线程,而且其最大线程数Integer.MAX_VALUE是一个很大的数,实际上就至关于最大线程数能够任意大.当线程池中的线程都处于活动状态时,线程池会建立新的线程来处理新任务,不然就会利用空闲的线程来处理新任务.线程池中的空闲线程都有超时机制,60秒,超过60秒的的闲置线程就会被回收.
CachedThreadPoll比较适合执行大量的耗时较少的任务
ScheduledThreadPoolExecutor继承自ThreadPoolExecutor。它的核心线程数量是固定的,而非核心线程数是没有限制的,而且当非核心线程闲置时会被当即回收.它主要用来在给定的延迟以后运行任务,或者按期执行任务。
本篇呢,记录了一下并发编程中经常使用的一些工具类以及java或者Android面试中基本必问的只是点线程池.关于并发编程的记录暂告一段落.后面可能会出番外篇.最近也入职了新公司,忙着适应新公司的时候好像怠慢了本身的积累.后面尽可能会按照一个月一篇的速度更新博客,感谢关注个人粉丝.
此致,敬礼