控制线程流

时间:2010-04-14 12:52:07

标签: java multithreading wait multitasking

我有一个任务是编写简单的游戏,模拟两个玩家一个接一个地拿起1-3个匹配,直到堆消失。我设法为计算机选择匹配的随机值,但现在我想进一步让人类玩游戏。这是我已经拥有的:http://paste.pocoo.org/show/201761/

Class Player是一个电脑玩家,而PlayerMan应该是人类。问题是,PlayerMan的线程应该等到匹配的正确值,但我不能让它以这种方式工作。逻辑如下:线程运行直到匹配等于零。如果玩家编号正确,则调用函数pickMatches()。减少表上的匹配数后,线程应该等待,并且应该通知另一个线程。我知道我必须使用wait()和notify(),但我不能把它们放好。 Class Shared保留当前玩家的值以及匹配数量。

public void suspendThread() {
    suspended = true;
}

public void resumeThread() {
    suspended = false;
}

@Override
public void run(){
    int matches=1;
    int which = 0;
    int tmp=0;
    Shared data = this.selectData();
    String name = this.returnName();
    int number = this.getNumber();

    while(data.getMatches() != 0){

        while(!suspended){

            try{             
                which = data.getCurrent();

                if(number == which){

                    matches = pickMatches();

                    tmp = data.getMatches() - matches;
                    data.setMatches(tmp, number);

                    if(data.getMatches() == 0){
                        System.out.println("                          "+
                            name+" takes "+matches+" matches.");
                        System.out.println("Winner is player: "+name);
                        stop();
                    }

                    System.out.println("                          "+
                            name+" takes "+matches+" matches.");

                    if(number != 0){
                        data.setCurrent(0);
                    }
                    else{
                        data.setCurrent(1);
                    }
                }
                this.suspendThread();
                notifyAll();
                wait();

            }catch(InterruptedException exc) {}    
        }
    }
}

@Override
synchronized public int pickMatches(){
    Scanner scanner = new Scanner(System.in);
    int n = 0;
    Shared data = this.selectData();

    System.out.println("Choose amount of matches (from 1 to 3): ");

        if(data.getMatches() == 1){
            System.out.println("There's only 1 match left !");
            while(n != 1){
                n = scanner.nextInt();
            }
        }
        else{
            do{
                n = scanner.nextInt();
            }
            while(n <= 1 && n >= 3);
        }
    return n;
}

}

3 个答案:

答案 0 :(得分:1)

好吧,首先我要说的是,我认为你比你需要的更强硬。如果是我,我会创建一个'GameMaster'课程,它的工作是循环并告诉每个玩家轮到他们的时候。你的玩家类不会有循环,只是一个takeTurn方法。这样您就可以从播放器类中删除等待/通知行为。

如果你想保留你的设计,我仍然会摆脱等待/通知并使用Semaphore。检查文档是否正确使用,但要点是你要删除suspend / resume方法并在循环顶部调用acquire()并在底部释放。只需确保构造函数中的公平性设置为true,这样你就不必担心玩家通过连续两次获取信号量锁来连续两次转弯。

答案 1 :(得分:1)

好的,所以我设法做到了没有等待()等。

http://paste.pocoo.org/show/201966/

答案 2 :(得分:1)

当您发现自己必须在线程之间建立通信以同步其执行时,只是为了发生指定的事件序列(例如轮流玩游戏),这是一个好的迹象,表明您可能拥有比你需要。

在这种情况下,考虑在Player类的各种扩展上执行takeTurn()方法的单个线程可能会让您的生活更轻松。你可以使Player成为一个抽象的基类,强制命令.takeTurn(),然后让HumanPlayer和MachinePlayer类封装对该方法中每种类型的玩家都有意义的代码。与大量的wait()和notify()相比,这应该使更多的玩家扩展相对微不足道。