http://www.trinea.cn/android/java-android-thread-pool/
http://blog.youkuaiyun.com/yaya_soft/article/details/24396357
http://blog.youkuaiyun.com/carrey1989/article/details/12002033
线程池使用
说到线程池,平时主要用的是Thread跟AsyncTask,虽然异步任务已经封装了线程池的使用,可没去看源码,里面真正的使用,是不清楚的。
所以,我们都会想为什么要用它?我认为线程池的好处在于,我们可以对开启的线程进行跟进,当不需要处理的时候可以将它干掉,同时当我们定义了一个线程池之后,可以复用线程而不需要开启更多线程,这点对于我们安卓开发是至关重要的,你开启的thread越多意味着你的app内存消耗越多,速度也就越来越慢,提高现有线程的复用是一个很不错的优化。
然后,让我们来看看,java给我们的提供的四种线程池:
newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
newFixedThreadPool实现:
public class DownTask implements Runnable {
private int x; //线程编号
public DownTask(int x) {
this.x = x;
}
public void run() {
System.out.println(x + " thread doing something!");
try {
TimeUnit.SECONDS.sleep(5L);
System.out.println("第" + x + "个线程休息完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class FixedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(2);
for (int i = 0; i < 50; i++) {
exec.execute(new DownTask(i));
}
}
}
newScheduledThreadPool实现:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);
所以,java线程池的使用,提升了程序的性能:
重用存在的线程,减少对象创建、消亡的开销,性能佳。
可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
提供定时执行、定期执行、单线程、并发数控制等功能。
以下是总结一些线程池使用的经验:
1、轻量级任务(Runnable对象、Thread对象、Callable对象)可以选择不固定大小的线程池来执行,或者任务数量很少,也可以选择。
2、重量级的线程,每个线程耗时、耗资源都很大,那么就应该考虑固定大小的线程池了。
3、线程池任务的添加执行是JVM内部机制控制的,你不用担心循环添加很多任务会把固定线程池的池子撑破。
4、线程池初始化数量是根据系统的性能等要求来测试决定的,不是凭空想象。
5、另外,多线程编程中,要注意释放一些不要的资源,以便重新利用。像那个巨大空循环,会耗费大量的cpu和内存,以致系统没能力去做别的事情了,如果for语句便利一个庞大的集合,遍历完成后,最好可以讲null赋给集合以便尽快被垃圾回收器回收掉。
6、线程池给多线程编程带来了极大的便利,但这个API本身描述很模糊。在使用线程池的时候,一定要注意关闭池的策略。如果忘记关闭了,程序会一直等待。