- 对线程池 “池”的理解
可以理解为工厂,如果工厂生产斧头,小王从工厂借了一把,当小王用完了,还给工厂,之后小李也可以借去用
复用已有资源
控制资源总量
你一个任务过来了,我发现池子里有没事干并且还活着的线程,来,拿去用,我也不用费事给你创建一条线程了,要知道线程的创建和销毁可都是麻烦事
你一个任务过来了,我发现池子的线程都在忙,并且现在池子的线程已经太多了,在不限制下去就要内存溢出了,来,排队去
线程池的作用
1、new Thread的弊端
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("--------");
}
}).start();
a. 每次new Thread新建对象性能差:每次都要经历新建,就绪,运行,阻塞,死亡
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。
2、相比new Thread,Java提供的四种线程池的好处在于:
a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。
Executors介绍
通过Executors可以获得四种线程池
Executors
ExecutorService service = Executors.newCachedThreadPool();
//创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。池中物任务时,超过60秒,会自动关闭线程池。
ExecutorService service = Executors.newSingleThreadExecutor();
// 单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。(测试时都是先进先出的规则)
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
//创建一个定长线程池,支持定时及周期性任务执行。ScheduledExecutorService为ExecutorService的子类
ExecutorService service = Executors.newFixedThreadPool(15);
//创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
例子
- 线程TestThread
public class TestThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()+"===="+ getPriority()+"----数据库操作---"+this.getName());
}
}
- 缓存线程池Executors.newCachedThreadPool();
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
Thread td = new TestThread();
service.execute(td);
}
- 单例线程池Executors.newSingleThreadExecutor();
ExecutorService service = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
Thread td = new TestThread();
service.execute(td);
}
// 打印结果
// 1523331778779====5----数据库操作---Thread-0
// 1523331779780====5----数据库操作---Thread-1
// 1523331780780====5----数据库操作---Thread-2
// 1523331781780====5----数据库操作---Thread-3
// 1523331782780====5----数据库操作---Thread-4
// 1523331783780====5----数据库操作---Thread-5
// 1523331784780====5----数据库操作---Thread-6
// 1523331785780====5----数据库操作---Thread-7
// 1523331786781====5----数据库操作---Thread-8
// 1523331787781====5----数据库操作---Thread-9
- 定时线程池Executors.newScheduledThreadPool(10);
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
for (int i = 0; i < 10; i++) {
Thread td = new TestThread();
service.schedule(td, 5, TimeUnit.SECONDS); // 添加任务5秒之后执行
}
- 定长线程池Executors.newFixedThreadPool(15);
ExecutorService service = Executors.newFixedThreadPool(15);
for (int i = 0; i < 10; i++) {
Thread td = new TestThread();
service.execute(td);
}
项目中的用法
package com.hesvit.common.task.execute;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* <p>
* 线程池创建
* <p>
* @author liuping
* @since 2017年12月26日
*/
public class TaskExecute {
// 创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
private static ExecutorService fixedThreadPool;
// 创建固定容量大小的缓冲池
private static ExecutorService singleThreadExecutor;
// 创建容量为1的缓冲池
private static ExecutorService cachedThreadPool;
public static ExecutorService newFixedThreadPool(int nThreads) {
if (fixedThreadPool == null)
return Executors.newFixedThreadPool(nThreads);
else
return fixedThreadPool;
}
public static ExecutorService newSingleThreadExecutor() {
if (singleThreadExecutor == null)
return Executors.newSingleThreadExecutor();
else
return singleThreadExecutor;
}
public static ExecutorService newCachedThreadPool() {
if (cachedThreadPool == null)
return Executors.newCachedThreadPool();
else
return cachedThreadPool;
}
public static void execute(Runnable task) {
newFixedThreadPool(6).execute(task);
}
}
TaskExecute.execute(new RefreshAppUserThread());// 刷新app用户信息
// 线程
public class RefreshAppUserThread extends Thread {
@Override
public void run() {
RedisUtil.refreshAppUser();
}
}
import redis.clients.jedis.Jedis;
@Component
public class RedisUtil {
/** 过时时间为2小时:2 * 60 *60 */
private static int EXPIRE_2_HOUR = 7200;
// 缓存所有App用户
private static String ALL_APP_USERS = "all_app_users";
public static List<User> refreshAppUser() {
return refreshAppUser(null);
}
/**
* 刷新App用户列表
* liuping
*/
public static List<User> refreshAppUser(Jedis redis) {
if (redis == null)
redis = MyJedisPool.getJedisObject();// 获得jedis实例
List<User> users = new ArrayList<>();
try {
User user = new User();
user.setLimit(-1);
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
UserService service = (UserService) context.getBean("userService");
users = service.selectByIndex(user);
if (null != users) {
JSONArray jsonArray = JSONArray.fromObject(users);
String struser = String.valueOf(jsonArray);
redis.set(ALL_APP_USERS, struser);
redis.expire(ALL_APP_USERS, EXPIRE_2_HOUR); // 设置过期时间
}
} catch (Exception e) {
logger.error("Failed to get wxuser from redis: {}", e.getMessage());
} finally {
MyJedisPool.recycleJedisOjbect(redis);
}
return users;
}
}