0

我在大学的 PacMan 游戏中工作,基本上我必须制作自己的 CyclicBarrier,因为我不能使用 Java 中的 CyclicBarrier 库。当幽灵到达特定位置(GhostGoal)时,此屏障将用于保留幽灵,并且他们必须等待更多幽灵,直到我的 CyclicBarrier 的构造函数中给出的最大幽灵。Ghosts 对象实现了可运行(线程)。

我以这种方式构建我的 CyclicBarrier:

public class Barreira {
    private int num_threads;
    private int count;
    
    public Barreira(int num_threads) {
        this.num_threads=num_threads;
    }
    
    public synchronized void await() {
        while(count < num_threads) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        notifyAll();    
    }
    
    public synchronized void adiciona() {
        count+=1;
    }
    
    public int getNumThreadsNaBarreira() {
        return count;
    }
    
    public synchronized void reset() {
        count=0;
    }

}

而我调用屏障的代码(在用名称 barreira 初始化它之后)以这种方式位于这个空白中:

public synchronized void arrivePosition(){
...

if((Object)floor[y][x] instanceof GhostGoal && entity instanceof Ghost ) {
            barreira.adiciona();
            barreira.await();
            
        }

}

但是,当一个幽灵到达该位置时,所有幽灵都停止移动,不仅是该位置的幽灵......基本上一切都冻结了,因为我的屏障中的等待称为barreira。

任何人都可以帮忙吗?

非常感谢。

我也在考虑这个解决方案(删除等待方法并仅使用 adiciona 方法:

public class Barreira {
    ...
    private List <Ghost> barreiraGhosts = new ArrayList<Ghost>();
    
public synchronized void adiciona(Ghost g) { //teste
    while(contador <num_threads) {
    try {
        contador+=1;
        barreiraGhosts.add(g);
        g.wait();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }
    notifyAll();
    for(Ghost b: barreiraGhosts)
        b.run();
    reset();
}

}


public synchronized void arrivePosition(){
    ...
    
if((Object)floor[y][x] instanceof GhostGoal && entity instanceof Ghost ) {
            barreira.adiciona(entity);
        }

}

什么是最好的解决方案?

4

1 回答 1

0

嗯...)这是我在评论中所说的:

public class Test {

    public static void main(String[] args) throws Exception {
        final Thread[] threads = new Thread[5];

        final Barreira barreira = new Barreira(threads.length);

        for (int i = 0; i < threads.length; i++) {
            final Thread thread = new Thread(() -> {
                System.out.println("I'm started");
                barreira.adiciona();
                try {
                    barreira.await();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                System.out.println("I'm finished");
            });
            threads[i] = thread;
        }

        for (final Thread thread : threads) {
            thread.start();
        }

        for (final Thread thread : threads) {
            thread.join();
        }
        System.out.println("All done");
    }

    public static class Barreira {
        private final int num_threads;
        private int count;

        public Barreira(int num_threads) {
            this.num_threads = num_threads;
        }

        public synchronized void await() throws InterruptedException { // it's a common pattern
            // to declare InterruptedException for possible long/time consuming operations
            while (count < num_threads) {
                wait();
            }
        }

        public synchronized void adiciona() {
            count += 1;
            notifyAll();
        }

        public synchronized int getNumThreadsNaBarreira() {
            return count;
        }

        public synchronized void reset() {
            count = 0;
        }
    }
}

奇迹般有效。我认为您在使用屏障时遇到问题,但不是屏障本身...

于 2021-04-16T17:51:58.357 回答