我已经部署了一个使用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,因为实际程序对于每个请求运行超过一个小时,所以我无法锁定该函数。此外,除了使用会话之外还有其他方式。
答案 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实例。
同步对该实例变量的访问只会在您的应用程序中造成瓶颈;不要这样做。