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 org.apache.log4j.Logger;
public class YhUserInfoManager extends BaseManager {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(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);
return login(json, sdata);
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 + "'}");
// 如果沒有就直接新增
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.executeUpdate(sql_insert);
} catch (Exception e) {
sdata.setResponseBody("{success:\"true\",code:\"99\",msg:\"登入失敗,請聯系管理者!\"}");
} else {
sdata.setResponseBody("{success:\"true\",code:\"99\",msg:\"認證失敗!\"}");
return true;