android多线程之线程池
2017-03-17 18:40
405 查看
一.线程简介
在Android应用开发中在进行耗时操作时,此时就要用到线程,由于UI线程不能进行耗时操作,否则就会造成ANR,话不多说下面直接干货。二.子线程中更新UI的原理
有时在子线程中执行完操作以后需要把结果回传到UI线程,但是由于异步操作,我们需要等待子线程执行完毕之后才更新UI,这时大家都会想到Handler ,Message这种消息传递机制进行线程的切换,其中的源码我在这里不再的分析,但是线程切换最本质的地方如下代码:
new Thread(new Runnable() { @Override public void run() { Looper looper = Looper.getMainLooper() looper.prepare(); //执行UI操作 looper.loop(); } }).start();
其实Handle 消息机制最本质的就是利用Looper实现线程切换。
三.与多线程有关的方法
1.Callable2.Future
3.FutureTask
4.Runnable
Runnable 在多线程中是最熟悉不过的,但是Runnable 和Future 可以应用在Thread中,而Callable和Future只能应用在线程中。下面看代码:
Runnable 接口
public interface Runnable { void run(); }
Runnable接口没有返回值
Callable 接口
public interface Callable<V> { V call() throws Exception; }
Callable 接口与Runnable接口不同的是一个泛型接口,它有一个泛型V的call()方法的返回值,而Runnable里面的run()方法执行完没有返回值;
Future接口
public interface Future<V> { boolean cancel(boolean var1); //该任务是否取消 boolean isCancelled(); //该任务是否执行完成 boolean isDone(); //得到返回结果,会发生阻塞 V get() throws InterruptedException, ExecutionException; V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException; }
相比于Callable 和Runnable ,Future提供了对执行任务的可控性,这样很大程度上方便对执行任务的操作。
FutureTask 类
public class FutureTask<V> implements RunnableFuture<V> { //代码省略 } public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }
FutureTask 实现了Runnable,这就是为什么他能应用于Thread中,下面我们通过一个例子来说明他们的区别!
public class FutureDemo { static ExecutorService mExecutor = Executors.newSingleThreadExecutor(); public static void main(String[] args){ testRunnable(); testCallable(); testFutureTask(); } private static void testFutureTask() { FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() { @Override public Integer call() throws Exception { return sum(5, 16); } }); mExecutor.submit(futureTask); try { System.out.println("=========testFutureTask====="+futureTask.get()); } catch (Exception e) { e.printStackTrace(); } } private static void testCallable() { Future<Integer> submit = mExecutor.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { return sum(5, 16); } }); try { System.out.println("=========testCallable====="+submit.get()); } catch (Exception e) { e.printStackTrace(); } } private static void testRunnable() { Future<?> submit = mExecutor.submit(new Runnable() { @Override public void run() { sum(5, 16); } }); try { System.out.println("=========testRunnable====="+submit.get()); } catch(Exception e) { e.printStackTrace(); } } private static int sum(int a, int b){ return a+b; } } 下附输出结果 =========testRunnable=====null =========testCallable=====21 =========testFutureTask=====21
通过这个demo正好验证上面的结果。
四.Android中的线程池
1.常规线程池直接上代码
public class ThreadManager { //线程池中线程数 private final int THREAD_FIXED = 10; //单例模式获取对象 private static ThreadManager sInstance = null; //线程池 private ExecutorService mExecutorService; private ThreadManager() { this.mExecutorService = Executors.newFixedThreadPool(THREAD_FIXED); } public static synchronized ThreadManager getInstance() { if (sInstance == null) { sInstance = new ThreadManager(); } c9f0 return sInstance; } //执行操作任务接口 public void submit(Runnable task) { this.mExecutorService.submit(task); } public Future<Integer> submit(Callable<Integer> task) { return this.mExecutorService.submit(task); } //关闭执行任务 public void shutdown() { if (!this.mExecutorService.isShutdown()) this.mExecutorService.shutdownNow(); } }
2.阻塞线程池
利用生产者和消费者模式来实现,并加上拒绝策略实现阻塞。直接上代码。
public class ThreadPoolManager { //核心线程数 private int corePoolSize = 4; //最大线程数 private int maximumPoolSize = 10; //保持时间 private long keepAliveTime =10; //时间单位 private TimeUnit unit = TimeUnit.SECONDS; //阻塞线程队列 private LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(); /** * 线程池,执行请求 */ private ThreadPoolExecutor threadPoolExecutor; private ThreadPoolManager(){ this.threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); //开启请求对列 threadPoolExecutor.submit(runnable); } public static ThreadPoolManager getInstance(){ return InstanceHolder.instance; } private static class InstanceHolder{ private static ThreadPoolManager instance = new ThreadPoolManager(); } /** * 暴露api,添加请求 */ public <T> void excute(FutureTask<T> futureTask){ if(null != futureTask){ try { workQueue.put(futureTask); } catch (InterruptedException e) { e.printStackTrace(); } } } private Runnable runnable = new Runnable() { @Override public void run() { while(true){ FutureTask futureTask = null; try { //阻塞就在这里 futureTask = (FutureTask) workQueue.take(); } catch (InterruptedException e) { e.printStackTrace(); }finally { //执行请求 if(null != futureTask){ threadPoolExecutor.execute(futureTask); } } } } }; /** * 拒绝策略,实现队列阻塞 */ private RejectedExecutionHandler handler = new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) { try { workQueue.put(new FutureTask<Object>(runnable,null)); } catch (InterruptedException e) { e.printStackTrace(); } } }; }
下面是调用方法
ThreadPoolManager.getInstance().excute(new FutureTask<Object>(new Callable<Object>() { @Override public Object call() throws Exception { return null; } }));
执行流程如下:
1.创建ThreadPoolManager单例对象;
2.在构造方法里面就创建线程并且执行任务Runnable
3.Runnable里面就从队列里面取出任务,最后执行任务
4.excute()方法就是往队列里面添加任务.
到此android的线程池分析完毕;
逆风的方向,更适合飞翔
相关文章推荐
- Android 多线程处理之多线程用法--线程池
- Android多线程(一)线程池
- Android 多线程之四种线程池
- java&android线程池-Executor框架之ThreadPoolExcutor&ScheduledThreadPoolExecutor浅析(多线程编程之三)
- android多线程以及线程池使用
- Android中的多线程处理(二)——使用线程池中的线程
- Android 多线程,线程池,并发处理以及ANR
- 【转】java&android线程池-Executor框架之ThreadPoolExcutor&ScheduledThreadPoolExecutor浅析(多线程编程之三)
- Android进阶——多线程系列之四大线程池的使用介绍
- Android多线程(五)线程池ThreadPoolExecutor机制浅析
- android 多线程 - 并行包线程池为例说说线程池的设计需求及使用
- java&android线程池-Executor框架之ThreadPoolExcutor&ScheduledThreadPoolExecutor浅析(多线程编程之三)
- 7、Android多线程与线程池
- Android多线程 线程池
- Android多线程操作——线程池管理综述
- Android多线程(一)线程池
- Android 多线程,线程池的使用
- Android多线程与线程池
- java 多线程 android线程池
- Android 多线程下载文件原理霸气解析介绍 -----线程池管理和任务队列 (2)