共享计数器未在并发服务器上按预期递增

时间:2011-12-14 19:13:35

标签: java concurrency atomicity

我正在尝试存储任何客户端从ServerProtocol类请求描述的次数。

目前,每次新客户加入时,计数器将从零增加。有任何想法吗?

专柜课:

public class Counter {

private int counter;

public synchronized int get() {
    return counter;
}

public synchronized void set(int n) {
    counter = n;
}

public synchronized void increment() {
    set(get() + 1);
}
}

ServerProtocol类的片段:

 case OPTIONS:
            if (theInput.equals("1")) {
                theOutput = "computer program description here  -- Another? Y or N";
                counter.increment();
                System.out.println(counter.get());
                state = ANOTHER;

上面的println方法是将计数器的当前值打印到服务器类中的终端:

ServerProtocol类:

public class ServerProtocol {

private static final int TERMS = 0;
private static final int ACCEPTTERMS = 1;
private static final int ANOTHER = 2;
private static final int OPTIONS = 3;
private int state = TERMS;

public String processInput(String theInput) {
    String theOutput = null;

    Counter counter = new Counter();

    switch (state) {
        case TERMS:
            theOutput = "Terms of reference.  Do you accept? Y or N";
            state = ACCEPTTERMS;
            break;
        case ACCEPTTERMS:
            if (theInput.equalsIgnoreCase("y")) {
                theOutput = "1. computer program 2. picture 3. e-book";
                state = OPTIONS;
            } else if (theInput.equalsIgnoreCase("n")) {
                theOutput = "Bye.";
            } else {
                theOutput = "Invalid Entry -- Terms of reference.  Do you accept? Y or N";
                state = ACCEPTTERMS;
            }
            break;
        case ANOTHER:
            if (theInput.equalsIgnoreCase("y")) {
                theOutput = "1. computer program 2. picture 3. e-book";
                state = OPTIONS;
            } else if (theInput.equalsIgnoreCase("n")) {
                theOutput = "Bye.";
            } else {
                theOutput = "Invalid Entry -- Another? Y or N";
                state = ACCEPTTERMS;
            }
            break;
        case OPTIONS:
            if (theInput.equals("1")) {
                theOutput = "computer program description here  -- Another? Y or N";
                counter.increment();
                counter.get();
                state = ANOTHER;

            } else if (theInput.equals("2")) {
                theOutput = "picture description here -- Another? Y or N";
                state = ANOTHER;

            } else if (theInput.equals("3")) {
                theOutput = "e-book description here -- Another? Y or N";
                state = ANOTHER;

            } else {
                theOutput = "Invalid Entry -- 1. computer program 2. picture 3. e-book";
                state = OPTIONS;
            }
            break;
        default:
            System.out.println("Oops");
    }

    return theOutput;
}
}

4 个答案:

答案 0 :(得分:3)

serverprotocol方法中的计数器实例是一个局部变量。因此,每次调用方法processInput时,都会创建一个新的计数器实例,其值为零。这就是原因。

答案 1 :(得分:2)

您是否多次调用processInput?

计数器不是静态的;每次初始化它(例如Counter counter = new Counter())时,计数值将重新初始化为0.要么将其设置为静态,要么确保它只被初始化一次。

答案 2 :(得分:1)

您没有指定ServerProtocol的生命周期,所以我不知道每次客户端调用服务器时是否创建它,例如它是Google App Engine中的servlet。

如果不是,您至少需要将Counter counter的移动定义从一个方法移到另一个类。所以Counter counter成为了班级成员。

PS。在当前代码中使counter静态可行,但从设计角度看它是不冷却的。

答案 3 :(得分:0)

不确定我是否得到你要求的内容,但如果你想要只有1个计数器,你可以将其static。这应该确保只有一个副本增加。这有帮助吗?

编辑:您可以阅读静态变量here