Java多线程优化之线程池
java标准库提供了ExecutorService接口表示线程池
创建这些线程池的方法都被封装到Executors这个类
一、FixedThreadPool
FixedThreadPool:线程数固定的线程池
public class ThreadPoolTest01 {
public static void main(String[] args) {
//创建一个线程数固定为6的线程池
ExecutorService es = Executors.newFixedThreadPool(6);
for (int i = 0; i < 6; i++) {
es.submit(new Task01("start task" + i));
}
// 关闭线程池:
es.shutdown();
}
}
class Task01 implements Runnable{
private final String name;
public Task01(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("start task " + name);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("end task " + name);
}
}
运行后:
start task start task0
start task start task3
start task start task1
start task start task2
start task start task4
start task start task5
end task start task3
end task start task2
end task start task5
end task start task1
end task start task4
end task start task0
二、CachedThreadPool
CachedThreadPool:线程数根据任务动态调整的线程池
public class ThreadPoolTest02 {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
es.submit(new Task02("start task" + i));
}
es.shutdown();
}
}
class Task02 implements Runnable{
private final String name;
public Task02(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("start task " + name);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("end task " + name);
}
}
运行后:
start task start task0
start task start task1
start task start task2
start task start task3
start task start task4
end task start task1
end task start task0
end task start task3
end task start task4
end task start task2
如果想控制线程池的大小呢?首先看一下Executors.newCachedThreadPool()方法的源码:
MAX_VALUE = 0x7fffffff
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to {@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources. Note that pools with similar
* properties but different details (for example, timeout parameters)
* may be created using {@link ThreadPoolExecutor} constructors.
*
* @return the newly created thread pool
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
可以这样实现:
int min = 5;
int max = 10;
ExecutorService es = new ThreadPoolExecutor(min, max,
60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
第一个参数min 表示这个线程池初始化了5个线程在里面工作
第二个参数max 表示如果5个线程不够用了,就会自动增加到最多10个线程
第三个参数60 结合第四个参数TimeUnit.SECONDS,表示经过60秒,多出来的线程还没有接到活儿,就会回收,最后保持池子里就5个
第四个参数TimeUnit.SECONDS 如上
第五个参数 new LinkedBlockingQueue() 用来放任务的集合
三、SingleThreadExecutor
SingleThreadExecutor:仅单线程执行的线程池
适用场景:任务需要定期反复执行
public class ThreadPoolTest03 {
public static ScheduledExecutorService ses = Executors.newScheduledThreadPool(4);
public static void main(String[] args) {
//一秒后执行一次性任务
ses.schedule(new Task03("one-time"), 1, TimeUnit.SECONDS);
//2秒后开始执行定时任务,每3秒执行
//FixedRate是指任务总是以固定时间间隔触发,不管任务执行多长时间
ses.scheduleAtFixedRate(new Task03("fixed-rate"), 2, 3, TimeUnit.SECONDS);
//2秒后开始执行定时任务,以3秒为间隔执行
//FixedDelay是指,上一次任务执行完毕后,等待固定的时间间隔,再执行下一次任务
ses.scheduleWithFixedDelay(new Task03("fixed-delay"),2,3,TimeUnit.SECONDS);
}
}
class Task03 implements Runnable{
private final String name;
public Task03(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("start task " + name);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("end task " + name);
}
}
注意
线程池在程序执行完必须要关闭
1.调用shutdown()时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。
2.调用awaitTermination()则会等待指定的时间让线程池关闭。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/119822.html