java(Android)线程池
系统启动一个新的线程的成本是比较高的,因为它涉及到了有操作系统的交互,当程序性要创建大量生存期很短暂的线程时,更应该考虑使用线程池。
线程池在启动时即创建了大量的空闲的线程,可以指定线程的数量,但一个Runnable对象传给线程池是,线程池就会启动一个线程来执行它们的run()方法。当run()方法执行完毕时,该线程并不会死亡,而是再次返回线程池中成为空闲状态。等待执行下一个Runnable对象的run()方法
线程池可以设置最大的并发线程数。
1、new Thread 的弊端
执行一个异步任务如果是new Thread:
new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start();
这样会有如下的弊端:
a.每次new Thread 新建对象的性能差
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机
c.缺乏更多功能,如定时执行,定期执行、线程中断
相比new Thread ,java 提供的四种线程池的好处在于:
a.重用存在的线程,减少对象的创建、消亡的开销,性能佳,减少CPU在创建、消除的开销。
比如:
假设在一台服务器完成一项任务的时间为T
T1 创建线程的时间
T2 在线程中执行任务的时间,包括线程间同步所需时间
T3 线程销毁的时间
显然T = T1+T2+T3。注意这是一个极度简化的假设。
可以看出T1,T3是多线程本身的带来的开销,我们渴望减少T1,T3所用的时间,从而减少T的时间。但一些线程的使用者并没有注意到这一点,所以在程序中频繁的创建或销毁线程,这导致T1和T3在T中占有相当比例。显然这是突出了线程的弱点(T1,T3),而不是优点(并发性)。
b.可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免阻塞
c.提供定时执行、定期执行、单线程、并发数控制等功能。
在Android中当同时并发多个网络线程时,引入线程池技术会极大地提高APP的性能
2、java 线程池
java 中有内置线程池 有两种线程池对象 ExecutorService----表示尽快执行线程的线程池(只要线程池中有空闲线程,就立即执行线程任务)、ScheduledExecutorService(scheduled 表示可以延迟后执行,是ExecutorService的子类)
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。参数表示保存的线程数,即使线程是空闲的也被保存在线程池中。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
使用线程池
JDK自身带有线程池的实现类ThreadPoolExecutor
ExecutorService 提供了三个方法
1、Future<?> submit(Runnable task) 将一个Runnable 对象提交给指定的线程池,线程池将在有空闲线程是执行Runnable对象代表的任务,其中Future对象代表Runnable任务的返回值--但是run()方法执行结束后返回Null ,但可以调用Future的isDone()、isCancelled()方法来获得Runnable对象的执行状态。
2、<T>Future<T> submit(Runnable task,T result) 将一个Runnable 对象提交给指定的线程池,线程池将在有空闲线程是执行Runnable对象代表的任务,其中Future对象代表Runnable任务的返回值--可以指定显示的返回值,result为线程执行结束后的返回值。
ScheduledExecutorService 代表可在指定延迟后或周期性地执行线程任务的线程池。
1、ScheduledFuture<V> schedule(Runnable command ,long delay,TimeUnit unit)
指定command 任务将在delay延迟后执行。
2、ScheduledFuture<V> scheduleAtFixedRate(Runnable command ,long delay,long period,TimeUnit unit) 指定command 任务将在delay延迟后执行。并设置频率重复执行,也就是在delay+period、delay+2*period.........(重复执行)
用完一个线程池后,应该调用该线程池的shutdown()方法,该方法将启动线程池的关闭序列,调用该方法后的线程池不再接收新任务,但会将以前所有已提交任务执行完毕。但线程池中的所有任务都执行完成后,池中的所有线程都会死亡。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。