为什么要使用多线程:
a).提高用户体验或者避免ANR
答:在事件待处理中需要使用多线程,否则会出现ANR效应,或者因为响应较慢导致用户体验较差。
1.解决耗时任务(文件IO、联网请求、数据库操作)
2.提高并发能力(同一时间处理更多事情)
3.防止ANR
4.避免掉帧(要达到每秒60帧,每帧必须16ms处理完)
b).异步
答:应用中有些情况并不一定需要同步阻塞去等待返回结果,可以通过多线程来实现异步的操作。例如:你的应用中某个Actiity需要从云端获取一张图片,加载图片比较耗时,这时需要使用异步加载,加载完成一个刷新一个。
c).多任务
多线程的创建:
1.继承Thread类实现多线程:
答:Thread本质上也是实现类Runable接口的一个实例,并且启动线程的唯一方法就是通过Thread类的start()实例方法。start方法是一个native方法,它将启动一个新线程,并执行run方法,通过自己的类直接extend Thread,并复写run方法,就可以启动新线程并执行自己定义的run方法。
2.实现Runable接口方式实现多线程
答:如果自己的类已经extends另一类,就无法直接extends thread,此时必须实现一个Runable接口,同时为了启动线程,需要首先实例化一个Thread,并传入自己已经实现好Runnalbe接口的目标对象。
3.实现Runnable和继承Thread区别
答:
1).一个类只能继承一个父类,存在局限,一个类可以实现多个接口
2).在实现Runnalbe接口的时候调用Thread(Runnable target)创建线程时,使用同一个Runnalbe实例,则建立多线程的实力变量也是共享的。但是通过继承Tread类是不能用一个实例建立多个线程,故而实现Runnable接口适用于共享,当然,继承Thread类也能够共享变量,能共享Thread类的static变量。
3).Runnable接口和Thread之间的联系:Thread类是Runnalbe的子类。
线程池的应用:
1)new Thread的弊端
a.每次New Thread新建对象性能差。
b.线程缺乏统一管理,可能无限制新建线程,占用过多系统资源导致死机或OOM
c.缺乏更多功能,如定时执行、定期执行、线程中断。
2.java线程池
a.重用存在的线程,减少对象创建、消亡的开销,性能佳
b.可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞
c.提供定时执行、定期执行、单线程、并发数控制等功能
newCachedThreadPool:一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则创建新线程
效果:如下图,如果没有Thread.sleep,会直接并发,可能会创建更多的新线程,否则,明显可见使用空闲的线程
newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出定线程会在队列中等待。
效果:如下图,固定最大3个线程,并发3次,睡眠之后,继续并发三次....
newSingleThreadPool:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO、LIFO、优先级)执行。
效果:newCachedThreadPool 效果也可以达到响应的操作。
newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。
观看视频:https://www.bilibili.com/video/BV1m4411r73w?t=247&p=12