最近自学的时候遇到了这么一个问题……
要求是这样的:
1.在数据库中新建一个用户状态表。里面包含2个字段。user_status(userid bigint,status int)
userid为自增。
status默认为0;
插入1000条记录。
2.写一个存储过程,从user_status表中获取一条status=0的userid字段的值,取出userid时,需要同时把这条记录对应的status从0修改为1.
3.开启2个线程,在线程中循环调用第2步中的存储过程,直到user_status表中记录全部取完(即status全部为1)。要求:在2个线程中取出的userid不能重复。并把取出的userid,打印到某个文件中,一行一个userid
第一点,没啥问题吧应该,我在数据库里建好了。
第二点的话,我写的存储过程是:
create procedure sp_getuserid
as
declare @userid int
select top 1 @userid=userid from user_status where status=0 order by newid()
update user_status set status=1 where status=0 and userid =@userid
select userid from user_status where userid=@userid
第三点的代码:
public class Status implements Runnable {
private int num;
@Override
public void run() {
Boolean flag = true;
while(flag)
{
flag=this.writeFile(this.getUserid());
}
}
@SuppressWarnings("unchecked")
public List<UserBean> getUserid() {
// 创建数据库连接
Connection conn = ConnectDb.Connect();
QueryRunner qRunner = new QueryRunner();
List<UserBean> list = new ArrayList<UserBean>();
try {
list = qRunner.query(conn, "exec sp_getuserid",
new BeanListHandler(UserBean.class));
} catch (Exception e) {
e.printStackTrace();
}
DbUtils.closeQuietly(conn);
return list;
}
public Boolean writeFile(List<UserBean> list) {
if (list.size()==0)
return false;
else {
try {
File file = new File("d:/test.txt");
if (!file.exists())
file.createNewFile();
FileOutputStream out = new FileOutputStream(file, true);
for (int i = 0; i < list.size(); i++) {
StringBuffer sb = new StringBuffer();
SimpleDateFormat df = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss:SSS");
sb.append(df.format(new Date()) + " \t"
+ list.get(i).getUserid()+ " \t"+this.getNum());
sb.append(System.getProperty("line.separator"));
out.write(sb.toString().getBytes("utf-8"));
}
out.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return true;
}
}
}
public static void main(String[] args) {
new Thread(new Status(1)).start();
new Thread(new Status(2)).start();
}
public Status(int num)
{
this.num=num;
}
}
可是到最后,我不能在txt里得到1000条数据,总是缺少一些条目,但是数据库里却更新了……
如果我把存储过程改为
create procedure sp_getuserid
as
Begin TransAction
declare @userid int
declare @errno int
set @errno=0
select top 1 @userid=userid from user_status where status=0 order by newid()
set @errno=@errno+@@error
update user_status set status=1 where status=0 and userid =@userid
set @errno=@errno+@@error
select userid from user_status where userid=@userid
set @errno=@errno+@@error
If @errno>0
Begin
rollback TransAction
end
Else
Begin
Commit TransAction
End
这样运行又会报死锁错误……
好吧,多线程的问题和存储过程不怎么会啊,求指教啊!!