public class MessageUtils extends Thread{
private boolean flag = true;
public void run() {
while (this.flag) {
try {
Thread.sleep(300000L);  //5分钟
} catch (InterruptedException e1) {
e1.printStackTrace();
}
while (true) {
autoValidator();
try {
Thread.sleep(300000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

//靠线程每5分钟运行提交一次
public void autoValidator(){
//…………
if(condition1){
sendMessage(id,type);
}
else if(condition2){
sendMessage(id,type);
}
//…………
}
//手动提交
 public static int sendMessage(String companyid, String type){
int result = 0;
//…………
return result;
 }}线程每五分钟运行一次autoValidator(),由于有时候sendMessage()向接口提交的数据量比较大,在页面手动运行sendMessage时接口那边的状态值还没返回来如果恰巧线程又在运行,会出现重复提交数据的现象,想用synchronized来解决,怎么解决?

解决方案 »

  1.   

    因为你的sendMessage()是static的,所以最简单的方式就是:public static synchronized int sendMessage(String companyid, String type){
      

  2.   

    synchronized是达不到目的的,后台应该设置一个标志来判断数据是否已经提交过
    synchronized只是协调线程工作,线程本身并不知道什么数据被提交过,什么没有被提交,加上synchronize只能让线程等待手动执行的结束后线程才执行,但并没有终止线程继续执行,所以线程还是会重复提交数据
      

  3.   

    可以一定义一个全局的static变量,通过改变他的状态来确定当期是否在发送数据
      

  4.   


    可以,但是相对就比较复杂些,要另外写个函数包装下,可以用一些标志位来进行控制。boolean[] flag = {false};checkAndSendMessage(...){
      synchronized (flag) {
        if (flag[0]) throw new RuntimeException("正在提交中");
        flag[0] = true;
      }
      sendMessage(...);
      flag[0] = false;
    }
    另外,3楼说的是有部分道理的,我相信你现在是靠提交后就清空提交数据这种做法,因此在串行化执行后不会发生重复提交;但需要注意控制的是:如果发生异常的情况下,是否会出现重复提交,或者漏了提交;比如偶发的网络连接中断啥的。
      

  5.   

    LZ还是没明白我说的,synchronized只是让你的手动和线程串行,也就是一个执行结束后另一个才能执行,但本身并没有中止运行,所以后者不知道前者已经执行过,后者还是会继续执行,需要设置一个状态标志来判断是否已经执行过
    另,你的手动提交是直接调用static方法还是什么,直接调用static方法就不是操作相同的实例,因为static属于类而不是实例,而static方法加上synchronized就相当于单线程,因为是锁Class对象,这样,两个不同的用户就不能同时提交,也要一个人提交完后另一个人才能提交,这样,如果两个人处理的业务是相干的,互斥还可以理解,如果两个人处理的业务完全不相干,就会造成性能低下。
      

  6.   


    我是通过解析接口返回来的xml中的状态值来判断是否改变字段status的值从而判断是否已经向接口成功提交了数据,因此我觉得如果是线程同步的话应该不会出现重复提交了吧