线程池的使用
new Thread的弊端:
1.不利于管理,线程的生产及销毁消耗资源,可能造成OOM。
线程池的好处:
1.统一管理,节约资源,并发控制
package tcc.test.ConcurrentProgramming;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* @author tcc:
* @version 创建时间:2021年8月24日 上午11:04:29 类说明 Java通过Executors提供四种线程池,分别为:
* newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
* newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
* newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
* newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
*/
public class FixedThreadPoolTest2 {
// newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
/**
* 超时时间/分钟
*/
public static final int TIMEOUT = 5;
public void testFixedThreadPool() {
// 也知道callable和Runnable的区别是callable可以有返回值,也可以抛出异常的特性,而Runnable没有
List<Callable<Boolean>> callableList = new ArrayList<Callable<Boolean>>();
Callable<Boolean> call = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
try {
return doYouMethod();
} catch (Exception e) {
System.out.println("执行异常:" + e);
return null;
}
}
};
callableList.add(call);
try {
System.out.println("callableList==" + callableList);
List<Future<Boolean>> futureList = fixedThreadPool.invokeAll(callableList);
for (Future<Boolean> future : futureList) {
Boolean flag = future.get(TIMEOUT, TimeUnit.MINUTES);
if (flag) {
System.out.println(" 成功");
} else {
System.out.println(" 失败");
}
}
} catch (Exception e) {
System.out.println(" ----- 异常 -----" + e.getMessage());
}
}
public synchronized Boolean doYouMethod() {
System.out.println(Thread.currentThread().getName());
System.out.println("doYouMethod");
return true;
}
public static void main(String[] args) {
FixedThreadPoolTest2 ft = new FixedThreadPoolTest2();
ft.testFixedThreadPool();
}
}
具体使用场景:与其他系统的单点登录,并发量高时,使用线程池newFixedThreadPool 控制并发数,并且使用同步代码块保证线程安全。
package com.sr.manager;
import asp.engine.core.manager.BaseManager;
import asp.engine.core.util.AspDaoUtil;
import com.alibaba.fastjson.JSONObject;
import com.sr.util.UserInfoUtils;
import com.sr.util.UserInfoUtils_xfm;
import com.util.DateUtils;
import com.util.FieldList;
import com.util.RowList;
import com.web.frame.SSOClient;
import jos.engine.core.ServiceData;
import jos.engine.core.jdbc.JdbcTemplate;
import jos.engine.encrypt.Encode;
import jos.framework.key.KeyUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
/**
* @author tcc:
* @version 创建时间:2021年8月24日 上午11:04:29 类说明 Java通过Executors提供四种线程池,分别为:
* newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
* newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
* newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
* newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
*/
public class YhUserInfoManager extends BaseManager {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
public static final int TIMEOUT = 5;
@SuppressWarnings("unused")
// 获取用户类型
public void getUserInfoutype(ServiceData sdata) {
String ticket = sdata.getRequest().getParameter("ticket");
log.info("第一步:" + ticket);
String result = UserInfoUtils.getUser(ticket);
log.info("第二步:" + result);
JSONObject json = JSONObject.parseObject(result);
log.info("第三步:" + json);
// 也知道callable和Runnable的区别是callable可以有返回值,也可以抛出异常的特性,而Runnable没有
List<Callable<Boolean>> callableList = new ArrayList<Callable<Boolean>>();
Callable<Boolean> call = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
try {
return login(json, sdata);
} catch (Exception e) {
System.out.println("执行异常:" + e);
return null;
}
}
};
callableList.add(call);
try {
System.out.println("callableList==" + callableList);
List<Future<Boolean>> futureList = fixedThreadPool.invokeAll(callableList);
for (Future<Boolean> future : futureList) {
Boolean flag = future.get(TIMEOUT, TimeUnit.MINUTES);
if (flag) {
System.out.println(" 成功");
} else {
System.out.println(" 失败");
}
}
} catch (Exception e) {
System.out.println(" ----- 异常 -----" + e.getMessage());
}
}
public synchronized Boolean login(JSONObject json, ServiceData sdata) {
if ("0".equals(json.getString("result"))) {
String name = json.getString("username");
String userid = json.getString("userid");
String gender = json.getString("sex");
String usersfz = json.getString("idnum");
String userTelephone = json.getString("telephone");
String mobile = json.getString("mobile");
String sql_user = "SELECT ukey,utype,userid FROM bd_user a WHERE usfz=? and uisuse=1 and uisdel=0";
RowList rowList = getJdbcTemplate().queryRowList(sql_user, new Object[] { usersfz });
// 多条数据救返回给前端多个类型
if (rowList.size() > 1) {
String utype = "";
for (int i = 0; i < rowList.size(); i++) {
FieldList field_user = rowList.get(i);
utype = utype + "," + field_user.get("utype");
}
utype = utype.substring(1);
sdata.setResponseBody("{success:\"true\",code:\"01\",msg:\"登录成功\",utype:'" + utype + "',sfz:'" + usersfz
+ "',ukey:'" + userid + "'}");
return true;
}
// 只有一条数据,直接登录
int size = rowList.size();
String aString = rowList.get(0).get("userid");
if (rowList.size() == 1 && rowList.get(0).get("userid") != "") {
FieldList field_user = rowList.get(0);
String utype = field_user.get("utype");
String userid_zlj = field_user.get("userid");
String up_ukey_sql = "update bd_user set ukey = ? where userid = ?";
JdbcTemplate jdbcTemplate = new JdbcTemplate("mzdb");
jdbcTemplate.startTransaction();
userid = utype + "_" + userid;
jdbcTemplate.executeUpdate(up_ukey_sql, new Object[] { userid, userid_zlj });
jdbcTemplate.commitTransaction();
String ssoParam = SSOClient.generateSSOParamTmp(userid);
log.info("登录成功");
log.info("登录认证参数:" + ssoParam);
sdata.setResponseBody("{success:\"true\",code:\"00\",msg:\"登录成功\",ssoParam:'" + ssoParam + "',utype:'"
+ utype + "',sfz:'" + usersfz + "',pk_id:'" + userid + "'}");
return true;
}
// 如果没有就直接新增
String userpkid = String.valueOf(KeyUtils.nextId());
String uxm = name;
String username = "zww_" + mobile + "_" + userpkid;
String utype = "999";
String userpass = Encode.encodeToHex("sr123456");
String ucjsj = DateUtils.formatDate("yyyy-MM-dd HH:mm:ss");
String uxnode = "33";
String usfz = usersfz;
userid = utype + "_" + userid;
String sql_insert = "INSERT INTO bd_user(userid, utype, uxm, username, userpass, ucjsj, uisshow, uisuse, uisdel, uxnode, uxid, ukey,usex,usfz,uphone,umobile) VALUES( "
+ userpkid + ", " + utype + ", '" + uxm + "', '" + username + "', '" + userpass + "', '" + ucjsj
+ "', 1, 1, 0, " + " '" + uxnode + "', '" + uxnode + "', '" + userid + "','" + gender + "', '"
+ usfz + "', '" + userTelephone + "', '" + mobile + "');";
try {
JdbcTemplate jdbcTemplate = new JdbcTemplate("mzdb");
jdbcTemplate.startTransaction();
jdbcTemplate.executeUpdate(sql_insert);
jdbcTemplate.commitTransaction();
String ssoParam = SSOClient.generateSSOParamTmp(userid);
sdata.setResponseBody("{success:\"true\",code:\"00\",msg:\"登录成功\",ssoParam:'" + ssoParam + "',utype:'"
+ utype + "',sfz:'" + usersfz + "',pk_id:'" + userid + "'}");
} catch (Exception e) {
sdata.setResponseBody("{success:\"true\",code:\"99\",msg:\"登录失败,请联系管理员!\"}");
return true;
}
} else {
sdata.setResponseBody("{success:\"true\",code:\"99\",msg:\"认证失败!\"}");
return true;
}
return true;
}
}