这个问题不知道应该叫多线程问题还是并发了情况:
下面的方法是用来生产 原料单号 的。(具体就是每次接收到ADD请求就去数据库获取最后一个记录,做+1操作,存入数据库,作为当前原料单的号码)问题:
当多个request请求来时,+1还没有做完,另一个请求就获取了原来的值,导致多个请求都是同样的 原料单号。。
我尝试锁定这个方法,本地用main 测试,有效。但是web 测试 无效。请大牛帮忙!! public synchronized String TPOID(String ProxyId) { GenIDBean newGB = new GenIDBean();
GenIDDao gd = new GenIDDao();
Date d = new Date();
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
Map<String, Object> mapO = new HashMap<String, Object>();
mapO.put("label0", 1);// 1=原料单号生成
mapO.put("prefix0", ProxyId);
mapO.put("datestr0", sd.format(d));
try {
List<GenIDBean> lst = gd.getIDL(1, mapO);
if (lst != null && lst.size() > 0) {
int isuffix = Integer.parseInt(lst.get(0).getSuffix()) + 1;
newGB.setSuffix(isuffix + "");
newGB.setPrefix(lst.get(0).getPrefix());
newGB.setDatestr(lst.get(0).getDatestr());
} else {
newGB.setSuffix(1 + "");
newGB.setPrefix(ProxyId);
newGB.setDatestr(sd.format(d));
} newGB.setLabel(1);
if (gd.addgb(newGB) > 0) {
return (newGB.getPrefix() + newGB.getDatestr() + newGB.getSuffix()).replaceAll("-", "");
}
} catch (BaseDAOException e) {
e.printStackTrace();
return "";
} catch (BaseDaoSupportException e) {
e.printStackTrace();
return "";
}
return "";
}
下面的方法是用来生产 原料单号 的。(具体就是每次接收到ADD请求就去数据库获取最后一个记录,做+1操作,存入数据库,作为当前原料单的号码)问题:
当多个request请求来时,+1还没有做完,另一个请求就获取了原来的值,导致多个请求都是同样的 原料单号。。
我尝试锁定这个方法,本地用main 测试,有效。但是web 测试 无效。请大牛帮忙!! public synchronized String TPOID(String ProxyId) { GenIDBean newGB = new GenIDBean();
GenIDDao gd = new GenIDDao();
Date d = new Date();
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
Map<String, Object> mapO = new HashMap<String, Object>();
mapO.put("label0", 1);// 1=原料单号生成
mapO.put("prefix0", ProxyId);
mapO.put("datestr0", sd.format(d));
try {
List<GenIDBean> lst = gd.getIDL(1, mapO);
if (lst != null && lst.size() > 0) {
int isuffix = Integer.parseInt(lst.get(0).getSuffix()) + 1;
newGB.setSuffix(isuffix + "");
newGB.setPrefix(lst.get(0).getPrefix());
newGB.setDatestr(lst.get(0).getDatestr());
} else {
newGB.setSuffix(1 + "");
newGB.setPrefix(ProxyId);
newGB.setDatestr(sd.format(d));
} newGB.setLabel(1);
if (gd.addgb(newGB) > 0) {
return (newGB.getPrefix() + newGB.getDatestr() + newGB.getSuffix()).replaceAll("-", "");
}
} catch (BaseDAOException e) {
e.printStackTrace();
return "";
} catch (BaseDaoSupportException e) {
e.printStackTrace();
return "";
}
return "";
}
解决方案 »
- ajax向servlet发送表单数据并返回至的问题,点击登录按钮页面没反应,下面是代码
- 急求:[Microsoft][SQLServer 2000 Driver for JDBC]Object has been closed.【附程序】
- 500错误的问题???
- 关于String字符窜替换的问题
- hql
- 新闻分段问题请教
- JSP中SQL语句不能换行?
- 怎样查jsp的帮助
- 从数据库中怎样保存形成一个自由删除、添加的树状的数据结构最后在网页上动态显示出其树状结构?
- tomcat配置问题,为何我的Servlet和Bean不好用????
- 如何快速的学习JAVA语言
- 用jd2chm.exe生成CHM文件的疑惑
从数据库方面来看,你这个写法就有点问题了,应该让数据库自己进行增加的动作,而不是select出来再update
可以考虑的办法是update中使用sql子句,或者写成一个存储过程,用存储过程加锁
我推测是这个原因:此方法所在的类的对象,每次请求都会被创建一个,导致加锁无效,可以考虑将此类做成单例,如果不能做成单例,那么就不要使用同步方法,另外找一个application中唯一的对象,对其加锁。也就是说,此方法每次执行都必须获取application中唯一的对象的锁。
未指定单线程情况下,servlet请求池预先在池中分配数个servlet实例,对于每个请求,会由池中的实例对象负责处理请求
如果数据库如mysql 不支持,试试 static Object LOCK;function(){
synchronized (LOCK) {
//do sth...
}
}如果还不行,试试 java自带的concurrent包
如:
java.util.concurrent.locks.Lock
}
你的main是怎么写的,贴出来看看