javaSE_多线程之线程池
1) 使用语法
先上一个简单的例子:
public static void useExecutorService(){
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; ++i){
executorService.execute(new Runnable(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
executorService.shutdown();
}
输出:
pool-1-thread-3
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-2
ExecutorService 用来管理线程池,创建的时候指定了最多有三个线程,每执行一次execute就会启动一个线程,如果已达到3个了,就等待。
调用shutdown后表示启动一个关闭命令,不再接受新任务,线程执行完后自动回收。
2) 线程池对象类型
线程池对象 | 说明 |
newCachedThreadPool | -缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse.如果没有,就建一个新的线程加入池中 -缓存型池子通常用于执行一些生存期很短的异步型任务 因此在一些面向连接的daemon型SERVER中用得不多。 -能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。 注意,放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止。 |
newFixedThreadPool | 任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子。 FixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器。 |
ScheduledThreadPool | -调度型线程池 -这个池子里的线程可以按schedule依次delay执行,或周期执行 |
SingleThreadExecutor | -单例线程,任意时间池中只能有一个线程 -用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE) |
3) 方法
① isShutdown
boolean isShutdown()
如果此执行程序已关闭,则返回 true。
② isTerminated
boolean isTerminated()
如果关闭后所有任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。
③ awaitTermination
boolean awaitTermination(long timeout,TimeUnit unit) throws InterruptedException
等待(阻塞)直到关闭或最长等待时间或发生中断
参数:
timeout - 最长等待时间
unit - timeout 参数的时间单位
返回:
如果此执行程序终止,则返回 true;如果终止前超时期满,则返回 false
抛出:
InterruptedException - 如果等待时发生中断
④ Submit
提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。
等等。。。。。。篇幅有限,方法略
4) 使用参数
例如说,我有20张票,分四个线程去卖,如何将这些信息传给各线程,并能不重复卖掉。
public static void useExecutorService(){
int threadCount = 4;
int ticket = 20;// 20 张票
int steplength = ticket/threadCount;
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
System.out.println(“useExecutorService start”);
for (int i = 0; i < threadCount; ++i){
final Integer index_begin = i*steplength + 1;
final Integer index_end = index_begin + steplength - 1;
executorService.execute(new Runnable(){
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + “ : “ + index_begin + “-“ + index_end);
}
});
}
System.out.println(“useExecutorService end”);
executorService.shutdown();
}
定义了四个线程,通过for循环来执行四次线程,这样刚好启动了四个线程。
每个线程在定义的时候就会使用两个变量,每次循环时变量值不一样,这样每个线程都有自己的参数。
输出:
useExecutorService start
useExecutorService end
pool-1-thread-3 : 11-15
pool-1-thread-1 : 1-5
pool-1-thread-2 : 6-10
pool-1-thread-4 : 16-20
可见输出正是我们想要的结果。这里的关键点就在于index_begin,index_end这两个变量,为什么它们能做到可以直接在线程中使用,而且其值就是当时循环时的值呢?就是因为它们被定义为了final。
execute(new Runnable(){
这种语法就叫匿名内部类。
局部内部类和匿名内部类只能访问局部final变量,详见知识点。
5) 判断所有子线程结束
isTerminated
boolean isTerminated()
如果关闭后所有任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。
返回:
如果关闭后所有任务都已完成,则返回 true
while(true){
**if**(executorService.isTerminated())\{
System.***out***.println("-----------page:" + pageNumber + " run over");
**break**;
\}
Thread.*sleep*(1000);
}
还没有评论,来说两句吧...