天天看點

線程池的使用

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;