资料链接http://blog.csdn.net/weihan1314/article/details/7983725点击打开链接
知道线程池的人应该都知道线程池的优点,以下列出:
1,重用线程池中的线程,避免因为频繁的创建线程带来的性能下降;
2,能有效的控制线程池的最大并发数,避免以为其共同抢占资源而造成的阻塞,
3,能够对线程进行简单的管理,提供制定间隔和定时执行。
线程池java提供了一个借口Executor,真正的线程池实现靠下面的ThreadPoolExecutor,提供了一系列的参数来配置线程池,通过配置参数来创建不同的线程池,因此我们重点理解ThreadPoolExecutor,
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler);
corePoolSize: 线程池维护线程的最少数量,即核心线程,如果allowCoreThreadTimeOut设置为true,即核心线程超时会被销毁,一般配置这个,所以核心线程会一直存在,不会被销毁。
maximumPoolSize:线程池维护线程的最大数量,
keepAliveTime: 线程池维护线程所允许的空闲时间
unit: 线程池维护线程所允许的空闲时间的单位
workQueue: 线程池所使用的缓冲队列
handler: 线程池对拒绝任务的处理策略
以此创建的线程池在执行任务时大致遵循以下原则,
1,任务来临时,当活动线程数未超过核心线程数量时会直接使用剩余的核心线程执行任务,
2,如果线程池中的活动线程数量已经达到核心线程的数量,则会将人物加入到任务队列中排队等待执行,
3,如果在步骤二中无法讲任务插入任务对列,证明任务队列已经满了,这个时候再来任务则会立即重新启动一个非核心线程来执行任务,但是此时如果超过设置的最大活动线程数量,那么系统会拒绝此任务,会抛出异常。
其实在安卓的asynctask中就使用了线程池来操作任务,他的源码中配置了核心线程数量为cpu核心数加1,任务队列最多可以容纳128个任务,最大线程数为cpu狠心数*2+1,也就是任务队列已满时还是可以启动非核心线程来执行任务。
以下内容为转载,地址http://www.trinea.cn/android/java-android-thread-pool/,
2、Java 线程池
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
(1). newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
ExecutorService
cachedThreadPool
=
Executors
.
newCachedThreadPool
(
)
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
final
int
index
=
i
;
try
{
Thread
.
sleep
(
index
*
1000
)
;
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
(
)
;
}
cachedThreadPool
.
execute
(
new
Runnable
(
)
{
@Override
public
void
run
(
)
{
System
.
out
.
println
(
index
)
;
}
}
)
;
}
|
线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
(2). newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
ExecutorService
fixedThreadPool
=
Executors
.
newFixedThreadPool
(
3
)
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
final
int
index
=
i
;
fixedThreadPool
.
execute
(
new
Runnable
(
)
{
@Override
public
void
run
(
)
{
try
{
System
.
out
.
println
(
index
)
;
Thread
.
sleep
(
2000
)
;
}
catch
(
InterruptedException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
(
)
;
}
}
}
)
;
}
|
因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。可参考PreloadDataCache。
(3) newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:
|
ScheduledExecutorService
scheduledThreadPool
=
Executors
.
newScheduledThreadPool
(
5
)
;
scheduledThreadPool
.
schedule
(
new
Runnable
(
)
{
@Override
public
void
run
(
)
{
System
.
out
.
println
(
"delay 3 seconds"
)
;
}
}
,
3
,
TimeUnit
.
SECONDS
)
;
|
表示延迟3秒执行。
定期执行示例代码如下:
|
scheduledThreadPool
.
scheduleAtFixedRate
(
new
Runnable
(
)
{
@Override
public
void
run
(
)
{
System
.
out
.
println
(
"delay 1 seconds, and excute every 3 seconds"
)
;
}
}
,
1
,
3
,
TimeUnit
.
SECONDS
)
;
|
表示延迟1秒后每3秒执行一次。
ScheduledExecutorService比Timer更安全,功能更强大,后面会有一篇单独进行对比。
(4)、newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
ExecutorService
singleThreadExecutor
=
Executors
.
newSingleThreadExecutor
(
)
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
final
int
index
=
i
;
singleThreadExecutor
.
execute
(
new
Runnable
(
)
{
@Override
public
void
run
(
)
{
try
{
System
.
out
.
println
(
index
)
;
Thread
.
sleep
(
2000
)
;
}
catch
(
InterruptedException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
(
)
;
}
}
}
)
;
}
|
个人总结:其实最常用的是
newFixedThreadPool来创建线程池,当然了我们在实际应用中使用线程池时可以配置信号量来优化任务管理,而不是一直将任务加入到任务队列,这样做对安卓的性能不是很好,最常见的就是图片加载框架,当任务来临时,并且任务数量未达到核心线程数,此时我们可以将任务加入我们自定义的任务队列中等待有闲置的核心线程,那么怎么控制任务数量达到核心线程数时等待呢,我们可以创建一个信号量,其数量的核心线程数量一致,如下:
-
- mThreadPool = Executors.newFixedThreadPool(threadCount);
- mTaskQueue = new LinkedList<Runnable>();
- mType = type;
- mSemaphoreThreadPool = new Semaphore(threadCount);
每当来任务时,
-
- mThreadPool.execute(getTask());
- try
- {
- mSemaphoreThreadPool.acquire();
- } catch (InterruptedException e)
- {
- }
此时信号量阻塞一个,当达到核心线程数量时信号量使用完了,新来的任务,则不接受,只有当任务执行完之后调用release()方法释放一个信号量,
mSemaphoreThreadPool.release();
再来任务时才会调用线程池中的线程进行任务处理,至此大概就总结完了,参考了很多大神的文章,自己总结来当笔记学习。