使用CompletionService结合ExecutorService批处理调用存储过程任务实例
此实例为java多线程并发调用存储过程实例,只做代码记载,不做详细描述
1.线程池构造初始化类CommonExecutorService.java
package com.pupeiyuan.go; import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; public class CommonExecutorService { private static final int CAPACITY = 10000;
private static final int CORE_POOL_SIZE = 100;
private static final int MAXIMUM_POOL_SIZE = 1000;
private static final Long KEEP_ALIVE_TIME = 100L; private CommonExecutorService() {
} public static ExecutorService getExecutorService() {
return executorService;
} /**
* 构造请求线程池,队列大小为1000
*/
private static final ExecutorService executorService = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,
KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(CAPACITY), new ThreadFactory() { AtomicInteger poolNumber = new AtomicInteger(1);
AtomicInteger threadNumber = new AtomicInteger(1); @Override
public Thread newThread(Runnable r) {
String namePrefix = String.format("reportPool-%s-thread-", poolNumber.getAndIncrement());
return new Thread(r, namePrefix + threadNumber.getAndIncrement());
}
});
}
2.基础任务类BaseTask并实现Callable
package com.pupeiyuan.go; import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Logger; public abstract class BaseTask implements Callable<Map<String, Object>>{ // protected static final Logger logger = Logger.getLogger(BaseTask.class);
/**
* 组织ID
*/
private String orgId;
/**
* 组织类型
*/
private String orgType;
/**
* 时间维度
*/
private String timeDim;
/**
* 指标列表
*/
private List<String> indexIdList;
/**
* 指标类别
*/
private String indexCategory;
/**
* 指标权限
*/
private Set<String> validIndexSet;
/**
* 存储过程名称
*/
private String procName;
/**
* 后台设置的有效指标集合
*/
private Set<String> backendValidIndexSet; /**
* 保存任务结果
*/
private Map<String, Object> taskResultMap; /**
* 记录日志用到的userId
*/
private String userId; public BaseTask() {
// TODO Auto-generated constructor stub
} @Override
public Map<String, Object> call() {
List<String> paramList = makeParamList();
ThreadUtils.set(getUserId());
List<Map<String, Object>> retListMap = callProc(paramList);
ThreadUtils.remove();
Map<String, Object> retMap = handleBiResult(retListMap);
this.setTaskResultMap(retMap);
return retMap;
} /**
* 构造请求参数
*
* @return
*/
public List<String> makeParamList() {
List<String> params = new ArrayList<String>();
//uuid to old_id
params.add(CommonConstant.getOldIdByUUID(getOrgId(),getOrgType()));
params.add(ReportUtils.getBIOrgType(getOrgType()));
params.add(getTimeDim());
if (getIndexIdList() != null && getIndexIdList().size() > 0) {
params.add(StringUtils.join(getIndexIdList(), ","));
}
if (StringUtils.isNotBlank(getIndexCategory())) {
params.add(getIndexCategory());
}
return params;
} private List<Map<String, Object>> callProc(List<String> paramList) {
System.out.println("thread:"+Thread.currentThread().getName()); CallProcedureIDao callProcedureIDao = SpringContextHolder.getBean(CallProcedureIDao.class);
List<Map<String, Object>> retListMap = null;
try {
retListMap = callProcedureIDao.getCallProcedureResult(getProcName(), paramList);
}
catch(Exception e) {
logger.error(e.getMessage(),e);
}
return retListMap;
} public abstract Map<String, Object> handleBiResult(List<Map<String, Object>> retListMap);
/**
* @return the orgId
*/
public String getOrgId() {
return orgId;
} /**
* @param orgId the orgId to set
*/
public void setOrgId(String orgId) {
this.orgId = orgId;
} /**
* @return the orgType
*/
public String getOrgType() {
return orgType;
} /**
* @param orgType the orgType to set
*/
public void setOrgType(String orgType) {
this.orgType = orgType;
} /**
* @return the timeDim
*/
public String getTimeDim() {
return timeDim;
} /**
* @param timeDim the timeDim to set
*/
public void setTimeDim(String timeDim) {
this.timeDim = timeDim;
} /**
* @return the indexIdList
*/
public List<String> getIndexIdList() {
return indexIdList;
} /**
* @param indexIdList the indexIdList to set
*/
public void setIndexIdList(List<String> indexIdList) {
this.indexIdList = indexIdList;
} /**
* @return the validIndexSet
*/
public Set<String> getValidIndexSet() {
return validIndexSet;
} /**
* @param validIndexSet the validIndexSet to set
*/
public void setValidIndexSet(Set<String> validIndexSet) {
this.validIndexSet = validIndexSet;
} /**
* @return the procName
*/
public String getProcName() {
return procName;
} /**
* @param procName the procName to set
*/
public void setProcName(String procName) {
this.procName = procName;
} /**
* @return the indexCategory
*/
public String getIndexCategory() {
return indexCategory;
} /**
* @param indexCategory the indexCategory to set
*/
public void setIndexCategory(String indexCategory) {
this.indexCategory = indexCategory;
} /**
* @return the statCommonIService
*/
public StatCommonIService getStatCommonIService() {
return SpringContextHolder.getBean(StatCommonIService.class);
} /**
* @return the sysContactsIService
*/
public SysContactsIService getSysContactsIService() {
return SpringContextHolder.getBean(SysContactsIService.class);
} /**
* @return the backendValidIndexSet
*/
public Set<String> getBackendValidIndexSet() {
return backendValidIndexSet;
} /**
* @param backendValidIndexSet the backendValidIndexSet to set
*/
public void setBackendValidIndexSet(Set<String> backendValidIndexSet) {
this.backendValidIndexSet = backendValidIndexSet;
} /**
* @return the taskResultMap
*/
public Map<String, Object> getTaskResultMap() {
return taskResultMap;
} /**
* @param taskResultMap the taskResultMap to set
*/
public void setTaskResultMap(Map<String, Object> taskResultMap) {
this.taskResultMap = taskResultMap;
} /**
* @return the userId
*/
public String getUserId() {
return userId;
} /**
* @param userId the userId to set
*/
public void setUserId(String userId) {
this.userId = userId;
} }
3.具体任务类继承BaseTask继承BaseTask
package com.pupeiyuan.go; public class PieTask extends BaseTask{ public PieTask() {
// TODO Auto-generated constructor stub
} public Map<String, Object>(List<Map<String, Object>> retListMap) {
Map<String, Object> retMap = new HashMap<String, Object>();
if (retListMap != null && retListMap.size() > 0) {
List<String> inputIdList = getIndexIdList();
Map<String, Object> map;
String indexId;
for(int i = 0; i < inputIdList.size(); i++) {
indexId = inputIdList.get(i);
map = retListMap.get(i);
if (map == null) {//空数据处理
retMap.put(indexId,makePieItem(indexId,CommonConstant.INDEX_VALUE_STAR,getValidIndexSet()));
} else {
String indexValue = (String)map.get("INDEX_VALUE");
retMap.put(indexId,makePieItem(indexId,indexValue,getValidIndexSet()));
}
}
} else {//空数据处理
retMap = makePieFakeData(getIndexIdList(),getValidIndexSet());
}
return retMap;
} //没有数据处理
public static HrPieItem makePieItem(String indexId, String indexValue, Set<String> validIndexSet) {
HrPieItem item = new HrPieItem();
IndexInfoVo indexObj = CommonConstant.getIndexObj(indexId);
if (indexObj == null) {
logger.error("ERROR:We dont find this indexId("+indexId+") info.");
return item;
}
//查看权限
boolean bValid = validIndexSet.contains(indexId);
bValid = true;
item.setIndexId(indexId);
String name = indexObj.getName();
String[] items = StringUtils.split(name, "\\|");
if (items != null ) {
if (items.length == 1) {
item.setIndexName(CommonConstant.getIndexNameWithDp(items[0],bValid));
} else if(items.length == 2) {
item.setIndexName(CommonConstant.getIndexNameWithDp(items[0],bValid));
item.setIndexShortName(CommonConstant.getIndexNameWithDp(items[1],bValid));
}
}
item.setIndexUnit(indexObj.getUnit());
item.setIndexValue(CommonConstant.getIndexValueWithDp(indexValue,bValid)); return item;
} //没有数据处理
public static Map<String, Object> makePieFakeData(List<String> indexIdList, Set<String> validIndexSet) {
Map<String, Object> retMap = new HashMap<String, Object>();
HrPieItem item;
for (int i = 0 ;i <indexIdList.size(); i++) {
String indexId = indexIdList.get(i);
item = makePieItem(indexId,CommonConstant.INDEX_VALUE_STAR,validIndexSet);
retMap.put(indexId, item);
}
return retMap;
}
//转换扇区百分比
public static void convertPercentage(List<HrPieItem> pieItems) {
Double sum = new Double(0);
//计算各扇区总和
for (HrPieItem hrPieItem : pieItems) {
if(null!=hrPieItem.getIndexValue()&&!"".equals(hrPieItem.getIndexValue())&&!"--".equals(hrPieItem.getIndexValue())) {
sum+=Double.parseDouble(hrPieItem.getIndexValue());
}
}
if(sum>0) {
//计算分区所占百分比
for (HrPieItem hrPieItem : pieItems) {
if(null!=hrPieItem.getIndexValue()&&!"".equals(hrPieItem.getIndexValue())&&!"--".equals(hrPieItem.getIndexValue())) {
double percentage = Double.parseDouble(hrPieItem.getIndexValue())/sum;
percentage = (double) Math.round(percentage * 10000)/100;
hrPieItem.setPercentage(String.valueOf(percentage)+"%");
}
}
}
}
4.多线程处理触发类TaskExecutor
package com.pupeiyuan.go; import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; public class TaskExecutor { private static ExecutorService commonExecutorService = CommonExecutorService.getExecutorService();
private static ExecutorCompletionService<Map<String, Object>> completionService = new ExecutorCompletionService<Map<String, Object>>(commonExecutorService); public TaskExecutor() {
} public static void compute(List<BaseTask> taskList) {
if (taskList != null && taskList.size() > 0) {
for (BaseTask task : taskList) {
completionService.submit(task);
} try {
for (int i = 0; i < taskList.size(); i++) {
Future<Map<String, Object>> future = completionService.take();
future.get(5000, TimeUnit.MILLISECONDS);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
}
5.调用存储过程实现类CallProcedureDaoImpl
package com.pupeiyuan.go; public class CallProcedureDaoImpl implements CallProcedureIDao { protected final Log logger = LogFactory.getLog(this.getClass()); private JdbcTemplate biJdbcTemplate; private JdbcTemplate jdbcTemplate; /**
*
* @param procedureName 存储过程名称包含预编译参数 {call testpro(?,?)} 最后一个参数为输出参数为游标类型
* @param params 对应存储过程执行参数是有顺序的,参数类型为字符类型 不包含存储的输出参数
* @return
*/
@Override
@SuppressWarnings("unchecked")
public List<Map<String,Object>> getCallProcedureResult(final String procedureName, final List<String> params) {
final String userId = (String) ThreadUtils.get();
final long startTime = System.currentTimeMillis();
//logger.info("开始调用存储过程【"+procedureName+"】,入参【" + JSON.toJSONString(params) + "】");
List<Map<String,Object>> resultList = null;
try {
resultList = (List<Map<String,Object>>) biJdbcTemplate.execute(
new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection con) throws SQLException {
String storedProc = procedureName;// 调用的sql
CallableStatement cs = con.prepareCall(storedProc);
for (int i=0; i< params.size();i++) {
cs.setString((i+1), params.get(i));// 设置输入参数的值
}
cs.registerOutParameter((params.size()+1),OracleTypes.CURSOR);// 注册输出参数的类型
return cs;
}
}, new CallableStatementCallback() {
public Object doInCallableStatement(CallableStatement cs) throws SQLException,DataAccessException {
List<Map<String,Object>> resultsMap = new ArrayList<Map<String,Object>>();
cs.execute();
ResultSet rs = (ResultSet) cs.getObject((params.size()+1));;// 此处值必须跟游标返回的值下标是统一个下标
if (rs!=null) {
ResultSetMetaData rsmd = rs.getMetaData();
List<String> columNames = new ArrayList<String>();
for(int i=1; i<= rsmd.getColumnCount(); i++){
columNames.add(rsmd.getColumnName(i)); //将字段名放在List中
}
if (!CollectionUtils.isEmpty(columNames)) {
while (rs.next()) {// 转换每行的返回值到Map中
Map<String,Object> rowMap = new HashMap<String,Object>();
for (String columName : columNames) {
rowMap.put(columName, rs.getObject(columName));
}
resultsMap.add(rowMap);
}
}
rs.close();
}
return resultsMap;
}
});
final long endTime = System.currentTimeMillis();
// logger.info("结束调用存储过程【"+procedureName+"】,入参【"+ JSON.toJSONString(params) + "】,查询存储过程返回数据条数【"+resultList.size()+"】总耗时:" + (endTime-startTime) + "毫秒");
// logger.info("本次调用存储过程返回数据:"+JSON.toJSONString(resultList));
final List<Map<String, Object>> finalResultList = resultList;
jdbcTemplate.update("INSERT INTO PROCEDURE_LOGS VALUES(?,?,?,?,?,?,?,?)",
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, JugHelper.generalUUID());
ps.setString(2, procedureName);
ps.setString(3, JSON.toJSONString(params));
ps.setString(4, JSON.toJSONString(finalResultList));
ps.setTimestamp(5, new Timestamp(new Date().getTime()));
ps.setInt(6, Integer.valueOf((endTime-startTime)+""));
ps.setString(7, "1");// 正常
ps.setString(8, AppStringUtils.isNotEmpty(userId) ? userId : "");// 用户ID
}
}
);
} catch (Exception e) {
final long endTime = System.currentTimeMillis();
final String errorMsg = getStackTrace(e);
jdbcTemplate.update("INSERT INTO PROCEDURE_LOGS VALUES(?,?,?,?,?,?,?,?)",
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, JugHelper.generalUUID());
ps.setString(2, procedureName);
ps.setString(3, JSON.toJSONString(params));
ps.setString(4, errorMsg);
ps.setTimestamp(5, new Timestamp(new Date().getTime()));
ps.setInt(6, Integer.valueOf((endTime-startTime)+""));
ps.setString(7, "0");// 异常
ps.setString(8, AppStringUtils.isNotEmpty(userId) ? userId : "");// 用户ID
}
}
);
}
return resultList;
} /**
* 获取完整的异常堆栈信息
* @param throwable
* @return
*/
protected String getStackTrace(Throwable throwable) {
StringWriter sw = null;
PrintWriter pw = null;
try {
sw = new StringWriter();
pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
finally {
if (sw!=null) {
try {
sw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (pw!=null) {
pw.close();
}
}
} public void setBiJdbcTemplate(JdbcTemplate biJdbcTemplate) {
this.biJdbcTemplate = biJdbcTemplate;
} public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
6.工具类ThreadUtils
package com.pupeiyuan.go; public class ThreadUtils { /*ThreadLocal:将变量与当前线程绑定*/
private static ThreadLocal<Object> threadLocal = new ThreadLocal<Object>(); public static void set(Object value) {
threadLocal.set(value);
} public static Object get() {
return threadLocal.get();
} public static void remove() {
threadLocal.remove();
}
}
7.业务类
package com.pupeiyuan.go; public class test {
//取出PIE的指标
List<String> pieWorkYearIndexList = HrIndexConstant.getPieWorkYearIndexList();
List<String> pieEducationIndexList = HrIndexConstant.getPieEducationIndexList();
List<String> pieCapacityIndexList = HrIndexConstant.getPieCapacityIndexList();
List<String> pieConsultorStarIndexList = HrIndexConstant.getPieConsultorStarIndexList();
List<String> pieRecruitChannelIndexList = HrIndexConstant.getPieRecruitChannelIndexList(); List<String> allIndex = new ArrayList<String>();
allIndex.addAll(pieWorkYearIndexList);
allIndex.addAll(pieCapacityIndexList);
allIndex.addAll(pieEducationIndexList);
allIndex.addAll(pieConsultorStarIndexList);
allIndex.addAll(pieRecruitChannelIndexList);
//获取指标权限
Set<String> validIndexSet = CommonConstant.getValidIndexList(orgId, postId, roleId, allIndex);
validIndexSet = HrIndexConstant.handleHrInnerPriv(validIndexSet,postId);
//
PieTask workYearTask = new PieTask();
workYearTask.setOrgId(orgId);
workYearTask.setOrgType(orgType);
workYearTask.setTimeDim(timeDim);
workYearTask.setIndexIdList(pieWorkYearIndexList);
workYearTask.setProcName(ProcedureConstant.PROC_HR_MAP.get("PROC_HR_PIE"));
workYearTask.setValidIndexSet(validIndexSet);
workYearTask.setUserId(userId); PieTask educationTask = new PieTask();
educationTask.setOrgId(orgId);
educationTask.setOrgType(orgType);
educationTask.setTimeDim(timeDim);
educationTask.setIndexIdList(pieEducationIndexList);
educationTask.setProcName(ProcedureConstant.PROC_HR_MAP.get("PROC_HR_PIE"));
educationTask.setValidIndexSet(validIndexSet);
educationTask.setUserId(userId); PieTask consultorStarTask = new PieTask();
consultorStarTask.setOrgId(orgId);
consultorStarTask.setOrgType(orgType);
consultorStarTask.setTimeDim(timeDim);
consultorStarTask.setIndexIdList(pieConsultorStarIndexList);
consultorStarTask.setProcName(ProcedureConstant.PROC_HR_MAP.get("PROC_HR_PIE"));
consultorStarTask.setValidIndexSet(validIndexSet);
consultorStarTask.setUserId(userId); PieTask recruitChannelTask = new PieTask();
recruitChannelTask.setOrgId(orgId);
recruitChannelTask.setOrgType(orgType);
recruitChannelTask.setTimeDim(timeDim);
recruitChannelTask.setIndexIdList(pieRecruitChannelIndexList);
recruitChannelTask.setProcName(ProcedureConstant.PROC_HR_MAP.get("PROC_HR_PIE"));
recruitChannelTask.setValidIndexSet(validIndexSet);
recruitChannelTask.setUserId(userId); /*CapacityPieTask capacityTask = new CapacityPieTask();
capacityTask.setOrgId(orgId);
capacityTask.setOrgType(orgType);
capacityTask.setTimeDim(timeDim);
capacityTask.setIndexIdList(pieCapacityIndexList);
capacityTask.setProcName(ProcedureConstant.PROC_HR_MAP.get("PROC_HR_PIE"));
capacityTask.setValidIndexSet(validIndexSet);
capacityTask.setUserId(userId); */ List<BaseTask> taskList = new ArrayList<BaseTask>(5);
taskList.add(workYearTask);
//taskList.add(capacityTask);
taskList.add(educationTask);
taskList.add(consultorStarTask);
taskList.add(recruitChannelTask); TaskExecutor.compute(taskList); //后续处理
List<HrPieData> pieList = new ArrayList<HrPieData>();
HrPieData pieData = new HrPieData();
pieData.setPieName("司龄分布");
pieData.setSubIndexList(getPieItemResult(pieWorkYearIndexList, workYearTask.getTaskResultMap()));
workYearTask.convertPercentage(pieData.getSubIndexList());
pieList.add(pieData); pieData = new HrPieData();
pieData.setPieName("学历分布");
pieData.setSubIndexList(getPieItemResult(pieEducationIndexList, educationTask.getTaskResultMap()));
educationTask.convertPercentage(pieData.getSubIndexList());
pieList.add(pieData); pieData = new HrPieData();
pieData.setPieName("经纪人星级分布");
pieData.setSubIndexList(getPieItemResult(pieConsultorStarIndexList, consultorStarTask.getTaskResultMap()));
consultorStarTask.convertPercentage(pieData.getSubIndexList());
pieList.add(pieData); pieData = new HrPieData();
pieData.setPieName("招聘渠道分布");
pieData.setSubIndexList(getPieItemResult(pieRecruitChannelIndexList, recruitChannelTask.getTaskResultMap()));
recruitChannelTask.convertPercentage(pieData.getSubIndexList());
pieList.add(pieData); }
使用CompletionService结合ExecutorService批处理调用存储过程任务实例的更多相关文章
- Web Services调用存储过程简单实例
转:http://www.cnblogs.com/jasenkin/archive/2010/03/02/1676634.html Web Services 主要利用 HTTP 和 SOAP 协议使商 ...
- oracle中job定时调用存储过程的实例
使用job模拟定时从元数据表中抽取指定数据进入目标表的过程. 一.创建元数据表 --create table test_origianl create table test_original_data ...
- 使用CompletionService结合ExecutorService批处理任务
CompletionService用于提交一组Callable任务,其take方法返回已完成的一个Callable任务对应的Future对象. 如果你向Executor提交了一个批处理任务,并且希望在 ...
- Command调用存储过程小实例
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx. ...
- jdbc执行预处理,批处理,LOB字段处理,调用存储过程
(1)jdbc执行预处理 PreparedStatment预备语句 eg:String sql="insert into user(id,name,birthday,money) value ...
- JDBC第二篇--【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】
这是我JDBC的第一篇 http://blog.csdn.net/hon_3y/article/details/53535798 1.PreparedStatement对象 PreparedState ...
- JDBC【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】
1.PreparedStatement对象 PreparedStatement对象继承Statement对象,它比Statement对象更强大,使用起来更简单 Statement对象编译SQL语句时, ...
- Java-JDBC调用批处理、存储过程、事务
一.使用Batch批量处理数据库 当需要向数据库发送一批SQL语句执行时,应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率.; 1.实现批处理有两种方式,第一种方式: S ...
- Java数据库连接——JDBC调用存储过程,事务管理和高级应用
一.JDBC常用的API深入详解及存储过程的调用 相关链接:Jdbc调用存储过程 1.存储过程(Stored Procedure)的介绍 我们常用的操作数据库语言SQL语句在执行的时候需要先编译,然后 ...
随机推荐
- Node.js创建服务器和模拟客户端请求
1. 何为服务器 服务器是某种长期运行,等待请求资源的应用程序 2. 常见Web应用架构 3. 如何创建web服务器 Web服务器是使用HTTP协议,等待客户端连接后请求资源的驻守应用程序:HTTP协 ...
- 使用lombok自动生成链式调用
本文转载:使用 Lombok 自动生成 Getter and Setter
- 用pip下载的python模块怎么在PyCharm中引入报错
在IDE中导入下载的模块,比如:numpy模块 你会发现虽然你安装了numpy模块,在CMD中python可以import numpy,但是你在PyCharm引不进去,为什么呢?你要是有注意的话,安装 ...
- python控制台输出带颜色的文字方法
#格式: 设置颜色开始 :\033[显示方式;前景色;背景色m 注意:开头部分的三个参数:显示方式,前景色,背景色是可选参数,可以只写其中的某一个:另外由于表示三个参数不同含义的数值都是唯一的没有 ...
- 【题解】放球游戏A
题目描述 校园里在上活动课,Red和Blue两位小朋友在玩一种游戏,他俩在一排N个格子里,自左到右地轮流放小球,每个格子只能放一个小球.每个人一次只能放1至5个球,最后面对没有空格而不能放球的人为输. ...
- CSS实现动画特效导航栏
0 写在前面 今天用纯CSS编写了一种带有特效的导航栏,一方面巩固熟悉了导航栏的一般写法,另一方面练习了CSS3的一些新特性. 1 实现效果 当鼠标划过时,实现了一种动态百叶窗效果. 2 实现细节 2 ...
- python Django 中间件介绍
我们一直都在使用中间件,只是没有注意到而已,打开Django项目的Settings.py文件,看到下面的MIDDLEWARE配置项,django默认自带的一些中间件: MIDDLEWARE = [ ' ...
- MySQL学习笔记(四)悲观锁与乐观锁
恼骚 最近在搞并发的问题,订单的异步通知和主动查询会存在并发的问题,用到了Mysql数据库的 for update 锁 在TP5直接通过lock(true),用于数据库的锁机制 Db::name('p ...
- LFYZ-OJ ID: 1009 阶乘和
思路 循环n次,每次计算i的阶乘i!,并加入sum中. n的范围从1~100,这里一定要使用高精度运算,涉及到"高精度乘低精度","高精度加高精度". 避免每次 ...
- fedora make: gcc:命令未找到(解决方法)
安装C开发环境 由于gcc包需要依赖binutils和cpp包,另外make包也是在编译中常用的,所以一共需要9个包来完成安装,因此我们只需要执行9条指令即可: yum install cpp yum ...