How to make my own CyclicBarrier without use CyclicBarrier from Java Library

176 views Asked by At

I am working in PacMan game for the University and basically I have to make my own CyclicBarrier, because I can't use the CyclicBarrier library from Java. This Barrier will be used to retain ghosts when they arrive to a specific position (GhostGoal) and they must wait for more ghosts until a maximum of ghosts that is given in the constructor of my CyclicBarrier. Ghosts objects implements runnable (Threads).

I was constructing my CyclicBarrier in this way:

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;
    }

}

And the code where I call the barrier (after initialize it with the name barreira) is in this void in this way:

public synchronized void arrivePosition(){
...

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

}

However when a ghost arrive to the position, all ghosts stop moving and not only the ghost that is in the position... Basically everything freeze, because of the wait in my Barrier called barreira.

Anyone can help?

Thank you very much.

I was thinking in this solution too ( delete await method and use only the adiciona method:

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);
        }

}

What is the best solution?

1

There are 1 answers

0
AnatolyG On

Hm...) Here is what I was talking about in my comment:

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;
        }
    }
}

works like a charm. I think you have an issue with using your barrier, but not the barrier itself...