目录
多线程
1 多线程的意义
(1)提高用户体验或者避免ANR(Application is not responding)
(2)异步
在应用程序中,有些情况下并不一定需要同步阻塞去等待返回结果,可以通过多线程来实现异步,如异步加载云端图片
2 多线程的创建
- 继承 Thread 类实现多线程
class MyThread extends Thread{ @Override public void run() { super.run(); Log.e("TAG:",Thread.currentThread().getName()+".run"); } }
- 实现 Runnable 接口
class MyRunnable implements Runnable{ @Override public void run() { Log.e("TAG:",Thread.currentThread().getName()+".run"); } }
- 实现 Callable 接口
//创建线程 class MyJob implements Callable{ @Override public Boolean call() throws Exception { for (int i = 0; i < 5; i++) { System.out.println("I am running thread"); } return true; } } //调用 MyJob thread = new MyJob(); // execute service,number of threads = 1 ExecutorService service = Executors.newFixedThreadPool(1); // submit to execute Future<Boolean> result = service.submit(thread); boolean r = result.get(); // get result service.shutdownNow(); // shut down the service System.out.println(r);
- 通过线程池
class MyTask implements Runnable{ int index = 0; public MyTask(int i){this.index = i;} @Override public void run() { Log.e("TAG:",Thread.currentThread().getName()+" "+index); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } ExecutorService cacheThreadPool = Executors.newCachedThreadPool(); ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(); ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); for(int i=1;i<=100;i++){ singleThreadPool.execute(new MyTask(i)); }
线程池
1. 线程池的应用
(1)new Thread的弊端
a)每次new Thread新建对象性能差
b)线程缺乏统一管理,可能无限制新建线程,相互竞争,可能占用过多系统资源导致死机或内存溢出oom
c)缺乏更多功能,如定时执行、定期执行、线程中断
(2)线程池好处
a)重用存在的线程,减少对象创建、消亡的开销,性能佳
b)可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞
c)提供定时执行、定期执行、单线程、并发数控制等功能
2. 线程池实现方式
1:ThreadPoolExecutor 基本线程池
2:FixedThreadPool (执行长期的任务,性能好很多)
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3:CachedThreadPool (适用于有大量需要立即执行的耗时少的任务的情况)
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
4:SingleThreadPool(一个任务一个任务执行的场景是的单个的FixedThreadPool )
创建一个单线程化的线程池,只会用唯一的工作线程来执行任务,保证所有任务按照指定的顺序(FIFO LIFO 优先级)执行。
5:ScheduledThreadPool(周期性执行任务的场景)
创建一个定长线程池,支持定时、周期性任务执行。
1,新建线程池
//创建基本线程池
final ThreadPoolExecutor threadPoolExecutor = new
ThreadPoolExecutor(3,5,1,TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(100));
/*创建fixed线程池,参数为核心线程数,
只有核心线程,无非核心线程,并且阻塞队列无界。
采用LinkedBlockingQueue
*/
final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
/*创建Cached线程池,没有核心线程,
只有非核心线程,并且每个非核心线程空闲等待的时间为60s,
采用SynchronousQueue队列。
*/
final ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
/*创建Single线程池,只有一个核心线程,当被占用时,
其他的任务需要进入队列等待,采用LinkedBlockingQueue
*/
final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
/*创建Scheduled线程池,延迟启动任务,
使用方法scheduledThreadPool.(runnable,10,TimeUnit.SECONDS);
*/
final ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
2 加入线程,几种线程池的使用方法都一样,除了ScheduledExecutorService ;
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
//处理相应事务
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
ScheduledExecutorService 使用方法
//10是指延时10s启动
scheduledThreadPool.(runnable,10,TimeUnit.SECONDS);
3 其他方法
1.shutDown() 关闭线程池,不影响已经提交的任务
2.shutDownNow() 关闭线程池,并尝试去终止正在执行的线程
3.allowCoreThreadTimeOut(boolean value) 允许核心线程闲置超时时被回收
4.submit 一般情况下我们使用execute来提交任务,但是有时候可能也会用到submit,使用submit的好处是submit有返回值。
5.beforeExecute() - 任务执行前执行的方法
6.afterExecute() -任务执行结束后执行的方法
7.terminated() -线程池关闭后执行的方法