日期:2014-05-17  浏览次数:20710 次

囧啊,今天面试,有两个问题没答出来,问问大家。谢谢!
第一个问题,先问Servlet是不是线程安全的?我回答“不是,因为只初始化一个Servlet对象,别的线程也可以访问。”然后他又问在Servlet里定义一个成员变量count用来计数,然后每次访问这个Servlet都给这个count+1,然后问我这样做好不好?我说“不好”。他又问我要怎么样解决,我就囧了,他说让我回家去网上查查,还说这个问题太普遍了。我晕。。。问问大家,怎么解决?

第二个问题,事务的权限有哪些?

------解决方案--------------------
应该这样回答:不是线程安全的,因为它是JAVA多线程技术,并且没有同步;定义成员变量来计数那是不行的,因为它是共享的数据,但没有同步不安全。可以解决的方式是自己加上同步代码,但更好的方法是利用JSP的APPLICATION这个对象。
------解决方案--------------------
问这问题可真好啊。。。我面个试问我SSH中都用到了什么设计模式。。。。。

servlet一般只有一个实例,所以如果这个servlet中有实例变量的话必须同步。在servlet上做同步虽然能保证正确性,但是对于服务器性能那绝对是灭顶之灾。。。所以面试官问你这样做好不好。你应该把计数变量放在更全局的域里面ServletContext中,然后对ServletContext中这个变量做同步。


同步代码不太会写哈。。貌似应该类似这样。。。

Java code

class Count {
    private int count;

    public int getCount() {
        return count;
    }

    public synchronized void add() {
        this.count += 1;
    }

}

------解决方案--------------------
lz,既然你都明白servlet不是線程安全的,那麽在裏面用 i++,i--等,又如何可以正確統計呢?

同步,要麽使用sysnchronized,要麽可以使用AtomicInteger。


AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。

来看AtomicInteger提供的接口。

//获取当前的值

public final int get()

//取当前的值,并设置新的值

 public final int getAndSet(int newValue)

//获取当前的值,并自增

 public final int getAndIncrement()

//获取当前的值,并自减

public final int getAndDecrement()

//获取当前的值,并加上预期的值

public final int getAndAdd(int delta)