【问题标题】:Can Java Objects reinstantiate on their own?Java 对象可以自行重新实例化吗?
【发布时间】:2013-08-27 14:23:47
【问题描述】:

我的应用程序中有一个进程通过 Servlet 将文档上传到我的服务器并等待完成,然后服务器使用 2 个线程处理文件,并在运行时保留 Status

Status 类的外观如下:

class Status implements Serializable {
    private Integer read;
    private Integer validated = 0;
    private Integer processed = 0;
    private Integer failed = 0;

    public Status (int read) {
        this.read = read;
    }

    /*
     *  Getter methods go here.
     *  No Setter methods.
     */

    public void incrementValidated() {
      synchronized(validated) { validated++; }
    }

    public void incrementProcessed() {
      synchronized(processed) { processed++; }
    }

    public void incrementFailed() {
      synchronized(failed) { failed++; }
    }
}

现在,服务器以这种方式处理文件:

  • 线程根据 DB 值验证读取的行,将正常的行放入队列中。
  • 线程一直等待,直到队列中有一批项目,然后将这批 X 项目持久化。

当项目正常 (incrementValidated)、项目持久化 (incrementProcessed) 和项目无效 (incrementFailed) 时更新 StatusStatus存储在一个ConcurrentHashMap<String, Status>中,其中key是用户的sessionID(因为这个进程可以处理多个请求)。

当进程运行时,客户端也在通过 Servlet 轮询服务器,它所做的只是return statusMap.get(sessionId);,直到进程完成。

我的问题出在运行时间过长的文件上,例如 5 分钟。当它运行并轮询服务器以获取状态时,有时所有值都设置回 0,唯一保持不变的值是 read 属性。
我不确定这怎么可能,因为该对象没有设置器,所以我只能想象该对象正在 re-instantiated 在构造函数上使用相同的值,因此保持相同的值。

这可能吗?还是我错过了什么?
(发生这种情况时,地址似乎发生了变化)

【问题讨论】:

  • 不,对象不能就地“重新实例化”。此外,您应该在 Status 类中使用 int 原始类型而不是 Integer
  • 你检查过你的servlet容器的配置吗?是不是你有一个 servlet 池而不是一个?
  • 你能贴出servlet的代码,即创建和修改状态的实体吗?

标签: java multithreading servlets


【解决方案1】:

您的同步已损坏。当您执行validated++; 时,您会创建一个新对象(请记住Integer 是不可变的)。所以其实根本就没有同步。

要解决此问题,请将原始类型的字段设置为 int(如评论中所建议的那样)并使三个方法同步。

int validated;

...

public synchronized void incrementValidated() {
  validated++;
}

【讨论】:

  • K,我试试这个,但是我不明白为什么Status 对象的地址会改变:(
  • Status 对象地址没有改变,它是在每次增量时分配的 Integer 对象。目前,您在 Integer 对象上进行同步。如果您看到Status 对象的地址发生变化,还有另一个原因。查看@autra 的评论
【解决方案2】:

您的同步无效。每次执行++ 时都会创建一个新对象,因此会在不同的对象上发生同步。

使用带有专用Object 锁或AtomicIntegers 的简单类型。

另外:您确定不需要用同一个锁同步所有整数变量吗?在这种情况下,您可以通过将方法标记为synchronized 来同步Status 本身。

【讨论】:

  • 是的,我确定它们不应该被整个对象同步,我不认为我会使用“专用对象锁”,但我会尝试上面的答案,或者使用 AtomicIntegers
猜你喜欢
  • 1970-01-01
  • 2017-03-17
  • 2010-09-17
  • 2022-08-04
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
相关资源
最近更新 更多