扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
多线程作为Android开发中相对而言较为高阶的知识,其中用到相关的知识点是非常的多,所以在我们需要进行设计或者写多线程的代码就必须要进行相对谨慎的处理,这样就由必要对其要有着比较系统化的认知
专注于为中小企业提供成都网站建设、网站制作服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业临沭免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
我们一般将Android应用分成为两种:主线程和工作线程;主线程主要是用来进行初始化UI,而工作线程主要是进行耗时操作,例如读取数据库,网络连接等
Android系统是以进程为单位来对应用程序资源进行限制,这个问题的可以解释为:一个进程最多能够开几个线程?最好能开几个?但实则这个是没有上限这一说,主要是因为资源的限制
Android中关于主线程的理解:Android的主线程是UI线程,在Android中,四大组件运行在主线程中,在主线程中做耗时操作会导致程序出现卡顿甚至出现ANR异常,一个.
在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。多线程处理一个常见的例子就是用户界面。
线程总的来就是进程的一个实体,是CPU进行分派和调度的基本单位,拥有着比进程更小且能够独立运行的基本单位,线程本身基本上是不拥有系统资源,仅拥有一点在运行过程中必须拥有的资源,但它可与同属一个进程中的其他进程进行共享其所拥有的所有资源
线程状态有些地方将之分为5中状态,而且在Java Jdk中线程被其定义为6中状态,我们可以对其进行类比
普遍定义的5中状态:新建,就绪,运行,阻塞, 死亡
Java Jdk 定义状态
线程阻塞是指在某一时刻的某一个线程在进行运行一段代码的情况下,突然另一个线程也要进行运行,但在运行过程中,那个线程执行完全运行之前,另一个线程是不可能获取到CPU的执行权,就会导致线路阻塞的出现
死锁也称之为抱死,意思就是说一个进程锁定了另外一个进程所需要的页或表是,但第二个进程同时又锁定了第一个进程所需的一页,这样就会出现死锁现象
简要介绍实现线程的三种方式:继承Thread,实现runnable,实现callable。这里有一点需要注意的是,实现callable是与线程池相关联的而callable很重要的一个特性是其带有返回值。当我们只需实现单线程时实现runnable更加利于线程程序的拓展
在线程开启之前进行调用 thread.setDaemon(true); 将thread设定成当前线程中的守护线程 使用案例
线程让步【yield方法】让当前线程释放CPU资源,让其他线程抢占
这种具体某个对象锁 wait notify 方法与Condition 的 await以及signal方法类似; 全面这种方法的阻塞等待都可以是释放锁,而且在唤醒后,这种线程都是能够获取锁资源的,而这个门栓就跟阀门类似
一、除了Thread外,扮演线程角色的还有:AsyncTask和IntentService,同时HandlerThread也扮演特殊的线程。
IntentService:内部采用HandlerThread来执行,像一个后台线程,同时是一个服务,不容易被系统杀死。
二、HandlerThread的run方法是一个无限循环
三、IntentService中任务是排队执行的
四、AsyncTask
1、Android1.6之前串行执行任务,1.6时候采用线程池里的并行,Android3.0开始又开始串行(为了避免并发错误),单任可以并行。
2、AsyncTask必须在UI线程调用(不过这个不是绝对的,和版本有关系,API 16之前,API 16到 22, API 22以后) 参考一
原因:内部有静态Handler,采用UI线程的Looper来处理消息,这就是为什么AsyncTask必须在UI线程调用,因为子线程默认没有Looper无法创建下面的Handler,程序会直接Crash
3、AsyncTask中有两个线程池和一个Handler,一个线程池用于任务排队,一个线程池用于真正的执行任务,InternalHandler用于将
执行环境从线程池切换到主线程
AsyncTask串行与并行
五、线程池
线程池中多余的线程是如何回收的
线程池的好处
1、重用线程池中的线程,避免线程的创建与销毁带来的性能开销
2、能有效控制线程池的最大并发数,避免大量线程因抢占资源而导致的阻塞
3、能对线程进行简单的管理,提供定时或者指定间隔时间、循环执行等操作
线程池的概率来自于java的Executor接口,实现类是ThreadPoolExecutor, 它提供一系列的参数来配置线程池,以此构建不同的线程池。Android的线程池分4类,都是通过Executors所提供的工厂方法来得到。
ThreadPoolExecutor有四个构造函数,下面这个是最常用的
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnnable workQueue, ThreadFactory threadFactory)
corePoolSize
线程池中的核心线程数,默认情况下核心线程会在线程池中一直存活,即使他们处于闲置状态。如果设置ThreadPoolExecutor 中的allowCoreThreadTimeOut = true, 核心线程在等待新任务到来时有超时机制,时间超过keepAliveTime所指定的时间后,核心线程会终止。
maximumPoolSize
最大线程数
keepAliveTime
非核心线程闲置的超时时间,超过这个时间,非核心线程会被回收。核心线程则要看allowCoreThreadTimeOut属性的值。
unit
时间单位
workQueue
线程池中的工作队列
threadFactory
线程工厂,为线程池提供创建新线程的功能。
举个例子,我们常用的okhttp内部也是使用了线程池,它的ThreadPoolExecutor主要是定义在Dispatcher类里面。 使用的是CachedThreadPool。
executorService = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS, SynchronousQueue(), ThreadFactory("okhttp Dispatcher", false))
1、FixedThreadPool
通过Executors的newFixedThreadPool()创建,这是一个线程数量固定的线程池,里面所有的线程都是核心线程。
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads, nThreads, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueueRunnable())
}
2、CachedThreadPool
通过Executors的newCacheThreadPool()创建,这是一个线程数量不定的线程池,里面所有的线程都是非核心线程。最大线程数是无限大,当线程池中的线程都处于活动状态时,新的task会创建新的线程来处理,否则就使用空闲的线程处理,所有的线程都是60s的超时时间,超时后会自动回收。
public static ExecutorService newFixedThreadPool(){
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueueRunnable())
}
3、ScheduledThreadPool
通过Executors的newScheduledThreadPool()创建, 核心线程固定,非核心线程无限大,当非核心线程空闲时,会立即被回收。适合做定时任务或者固定周期的重复任务。
public static ExecutorService newScheduledThreadPool(int corePoolSize){
return new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.SECONDS, new DelayedWorkQueue())
}
4、SingleThreadExcecutor
通过Executors的newSingleThreadPool()创建,内部只有一个核心线程。
public static ExecutorService newFixedThreadPool(){
return new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueueRunnable())
}
课外知识:LinkedBlockingQueue
LinkedBlockingQueue是由链表组成的阻塞队列,内部head 指向队列第一个元素,last指向最后一个元素。入队和出队都会加锁阻塞,都是使用了不同的锁。
DelayedWorkQueue
延时队列,队内元素必须是Delayed的实现类。对内元素会按照Delayed时间进行排序,对内元素只有在delayed时间过期了才能出队。
入队的时候不阻塞队列,出队的时候,如果队列为空或者队列里所有元素都等待时间都没有到期,则该线程进入阻塞状态。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流