并发servlet请求会覆盖静态值

时间:2014-08-02 04:43:24

标签: java multithreading java-ee servlets synchronization

我已经部署了一个使用servlet的简单Java Web应用程序。我遇到了并发请求的问题。

示例程序:

Public Class Test {
 static int num;
 public Test(){
 }
 public void setVal{
  Date dd = new Date();
  this.num = dd.getTime.toString()
 }
 public int getVal {
  return this.num;
 }
}

Public Class Print {
 Function generateID{
  Test test = new Test();
  test.setVal();
  Thread.sleep(10000);
  System.out.print(test.getVal() );
 }
}

假设Request1从类Print调用generateID。当请求1休眠10秒时,request2到来并调用相同的函数generateID。函数setVal()将覆盖num的值。同时,请求1打印数字的覆盖值

如何使这些请求彼此独立并且彼此不重叠。我不想使用synchronized,因为实际程序对于每个请求运行超过一个小时,所以我无法锁定该函数。此外,除了使用会话之外还有其他方式。

4 个答案:

答案 0 :(得分:0)

正如Sotirios Delimanolis在评论中所说,你应该在java中使用synchronized关键字来锁定线程。

同步方法启用了一种简单的策略来防止线程干扰和内存一致性错误:如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的。

public void synchronized generateID{
  Test test = new Test();
  test.setVal();
  Thread.sleep(10000);
  System.out.print(test.getVal() );
 }

答案 1 :(得分:0)

您需要设计您的应用程序,以便原子操作在尽可能少的时间内完成。

在您的情况下,您可以在setGetVall()课程中创建其他同步 Test方法:

public int synchronized setGetVal() {
    setVal();
    return getVal()
}  

然后你会有

public void generateID() {
  Test test = new Test();
  int final newValue = test.setGetVal();
  Thread.sleep(10000);   // and now it can safely sleep as long as it wants
  System.out.print( newValue );
}

对于更复杂的案例,您需要more sophisticated locking,但原则保持不变。

答案 2 :(得分:0)

我建议你看一下ThreadLocal,它提供了在线程中创建局部变量的权限。链接在这里。希望这能解决您的问题。

http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html

答案 3 :(得分:0)

Servlet并不意味着您不希望在多个线程之间提供实例变量。任何时候都存在单个servlet的单个实例;对servlet的每个请求都在它自己的堆栈中执行,它自己的线程,但是只有一个servlet实例。

同步对该实例变量的访问只会在您的应用程序中造成瓶颈;不要这样做。