【求助】关于java集合中的问题

谁抢我ID 2014-10-17 10:31:13
现在问题呢就是,我有一个线程在一直的跑,而在这个线程中有个查询数据库的方法,也就是说我要做的事是一直查询数据库,把查询到的数据取出来,放入集合中,然后把取出来的数据调用webservice接口,把数据推送过去,但是这样做的后果呢就是在向webservice发送数据的时候,会重复发送很多已经发送过的数据,而且还是一直不停的发,我看了下数据库,有条记录发送了75次、怎么才能避免这样的问题呢?
是在数据插入集合的时候做个判断还是怎么的?
各位大神请求帮助啊、
有方法的请给点代码和文字上的提示好不。
...全文
305 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
lliiqiang 2014-10-21
  • 打赏
  • 举报
回复
判断数据是否已经存在(一般用id判断),有了就不要再发送了,或者发送的时候判断一下是否已经发送,当然要有一个集合作为缓冲证明哪些已经被发送.对于第一个方案要做到集合不被删除,发送如果要删除数据,可以用另外一个集合复制删除发送数据,当然也可以在逻辑上客户端接收的时候处理,其实就是缓冲区在客户端而已.
谁抢我ID 2014-10-19
  • 打赏
  • 举报
回复
引用 13 楼 rumlee 的回复:
[quote=引用 12 楼 u010531369 的回复:] [quote=引用 11 楼 humanity 的回复:] 我觉得这种情况应该在数据库的表上有一个字段记录着发送日期,当它不为空时表示已经发送过了。
但是也还是有重复数据的、昨天我测试过,在我程序运行的没多久的时候,我改了数据库的标志位。 每次取100条,到200条的时候有3条重复的,到300条的时候有4条是重复的、[/quote] 1、要么是你用多个线程在发送,而多个线程获取数据的时候没有很好的用事务控制 2、你的sql语句错误 3、程序本身逻辑就错了 通过你描述的情况已经无法为你诊断,其实这个问题真的很简单,只要你每次获取数据的时候,将数据设置成正在发送状态(这两步需要通过事务控制,而且一开始获取数据的时候必须要使用for update加锁),发送成功了之后更新为发送成功状态。可以考虑增加一个设置,处于正在发送状态的信息如果超过一个设置时间,则视为发送失败。[/quote] 可以确定的是sql语句没有错,我是在用线程发送数据,而查询的方法我是写在一个while循环里面的,让它一直查询数据库,但是这样子有很多的重复数据往集合里放
rumlee 2014-10-19
  • 打赏
  • 举报
回复
引用 12 楼 u010531369 的回复:
[quote=引用 11 楼 humanity 的回复:] 我觉得这种情况应该在数据库的表上有一个字段记录着发送日期,当它不为空时表示已经发送过了。
但是也还是有重复数据的、昨天我测试过,在我程序运行的没多久的时候,我改了数据库的标志位。 每次取100条,到200条的时候有3条重复的,到300条的时候有4条是重复的、[/quote] 1、要么是你用多个线程在发送,而多个线程获取数据的时候没有很好的用事务控制 2、你的sql语句错误 3、程序本身逻辑就错了 通过你描述的情况已经无法为你诊断,其实这个问题真的很简单,只要你每次获取数据的时候,将数据设置成正在发送状态(这两步需要通过事务控制,而且一开始获取数据的时候必须要使用for update加锁),发送成功了之后更新为发送成功状态。可以考虑增加一个设置,处于正在发送状态的信息如果超过一个设置时间,则视为发送失败。
sinat_22191533 2014-10-19
  • 打赏
  • 举报
回复
请教在网页中制作合作账号登陆功能。
谁抢我ID 2014-10-19
  • 打赏
  • 举报
回复
引用 11 楼 humanity 的回复:
我觉得这种情况应该在数据库的表上有一个字段记录着发送日期,当它不为空时表示已经发送过了。
但是也还是有重复数据的、昨天我测试过,在我程序运行的没多久的时候,我改了数据库的标志位。 每次取100条,到200条的时候有3条重复的,到300条的时候有4条是重复的、
humanity 2014-10-19
  • 打赏
  • 举报
回复
我觉得这种情况应该在数据库的表上有一个字段记录着发送日期,当它不为空时表示已经发送过了。
谁抢我ID 2014-10-18
  • 打赏
  • 举报
回复
引用 7 楼 humanity 的回复:
你只有一个线程在后台做这件事,因此,你在发送的时候把集合复制一份。

List  原来的 ...;

List 准备发送的 = new ArrayList(原来的);

Sender s ...;
s.send(准备发送的);

原来的.removeAll(准备发送的) ; // 把已经发送的所有对象从原来的集合中删除掉。
注意如果你是一个线程准备数据,另一个线程发送,你就需要在修改这个集合时使用同步锁。如果你是单一线程发送,那你发送完了清空集合,另外你从数据库中发现发送了75次那表示你发送成功后会记录它已经发送了?那下次取的时候不要再选它了。 readFromSocket 这个表示对方出错了,可能是你给的数据有问题,也可能是对方自己出了其它问题,所以你先确认一下数据没有问题。
我现在是一个线程在工作的,用的是queue集合,您说的方法是在我调用对方的接口方法后就执行removeall?把集合内的数据都清空掉?我这个线程是一直在扫描数据库的。 还有就是readFromSocket 这个错误是参数问题还是接口出现了问题?我原来写了个测试方法,是可以通过的、但是现在执行那个测试方法的时候也报上面的错误了、
humanity 2014-10-18
  • 打赏
  • 举报
回复
你只有一个线程在后台做这件事,因此,你在发送的时候把集合复制一份。

List  原来的 ...;

List 准备发送的 = new ArrayList(原来的);

Sender s ...;
s.send(准备发送的);

原来的.removeAll(准备发送的) ; // 把已经发送的所有对象从原来的集合中删除掉。
注意如果你是一个线程准备数据,另一个线程发送,你就需要在修改这个集合时使用同步锁。如果你是单一线程发送,那你发送完了清空集合,另外你从数据库中发现发送了75次那表示你发送成功后会记录它已经发送了?那下次取的时候不要再选它了。 readFromSocket 这个表示对方出错了,可能是你给的数据有问题,也可能是对方自己出了其它问题,所以你先确认一下数据没有问题。
谁抢我ID 2014-10-18
  • 打赏
  • 举报
回复
引用 3 楼 shixitong 的回复:
再往集合里加的时候,最好也要判断是这个集合中是否已经这样的数据
集合我用的是queue集合 这个怎么判断呢?我用的是jdbc,是在while(rs.next){是在这用if判断吗cache.queue.offer(对象)}?
谁抢我ID 2014-10-18
  • 打赏
  • 举报
回复
引用 1 楼 rumlee 的回复:
在数据库增加一个字段,是否已经发送,对于发送过的数据不再发送就可以了。 循环扫描数据库的时候中间最好有一点点的间隔,具体间隔时间根据你的系统对实时性的要求,如果实时性要求不高的话,则间隔时间长点,如果实时性要求高,则间隔短点。
我刚刚用queue集合和map集合都试过了,而且数据库也有一个字段是表示发送成功的数据、每次只取一百条的话在一百条之内有2条重复的,但是到了200-300条的时候重复数据会+1变成3了、这个怎么搞呢
rumlee 2014-10-17
  • 打赏
  • 举报
回复
在数据库增加一个字段,是否已经发送,对于发送过的数据不再发送就可以了。 循环扫描数据库的时候中间最好有一点点的间隔,具体间隔时间根据你的系统对实时性的要求,如果实时性要求不高的话,则间隔时间长点,如果实时性要求高,则间隔短点。
谁抢我ID 2014-10-17
  • 打赏
  • 举报
回复
给位帮看一下,早上的时候这webservice还能调用,刚刚启动项目的时候,就报这个错误了 该怎么解决呢
谁抢我ID 2014-10-17
  • 打赏
  • 举报
回复
AxisFault faultCode: {http://xml.apache.org/axis/}HTTP faultSubcode: faultString: (0)null faultActor: faultNode: faultDetail: {}:return code: 0 {http://xml.apache.org/axis/}HttpErrorCode:0 (0)null at org.apache.axis.transport.http.HTTPSender.readFromSocket(HTTPSender.j ava:744) at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144) at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrateg y.java:32) at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118) at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83) at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165) at org.apache.axis.client.Call.invokeEngine(Call.java:2784) at org.apache.axis.client.Call.invoke(Call.java:2767) at org.apache.axis.client.Call.invoke(Call.java:2443) at org.apache.axis.client.Call.invoke(Call.java:2366) at org.apache.axis.client.Call.invoke(Call.java:1812) at com.dic.diass.util.WsdlUtil.callWebService(WsdlUtil.java:277) at com.dic.diass.dao.GTbwfsjJGThread.run(GTbwfsjJGThread.java:61)
XiaoFan012 2014-10-17
  • 打赏
  • 举报
回复
如果不改变数据库的情况下,在发送前对数据进行缓存; 感觉你的数据应该是最新数据,可能查询会重复,但这种数据一般会有一个排序,比如时间等, 把这个关键数据域作为发送前的判断可能会有用。
shixitong 2014-10-17
  • 打赏
  • 举报
回复
再往集合里加的时候,最好也要判断是这个集合中是否已经这样的数据
福来哥 2014-10-17
  • 打赏
  • 举报
回复
1,必须要增加字段表明数据发送状态。 2,查询《待发送》的数据后立刻把数据库里的标记成《正在发送》 3,数据推送结束后把数据库里的标记成《已经发送》

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧