views:

79

answers:

1

I'm trying to write a Java serial device driver and want to use the (new to me) java.util.concurrent package. I have one method which sends a packet then waits for an ACK. I plan to have char. reception run in a different thread. If the receive thread gets an ACK it should notify the thread with the send packet function. The receive thread implements a state machine and should notify any listeners of decoded packets.

I think I know how to do this using direct Threads, wait, notify etc., but am not sure how to do this with the new concurrent package. Would be very grateful for any pointers.

+2  A: 

Use a CyclicBarrier. Here's a cite of relevance from its Javadoc:

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.

So, you need to create a CyclicBarrier for a number of 2 parties and let the receiver thread invoke await() after ACK and let the sender thread invoke await() before doing the SEND.

Here's an SSCCE to get you started.

package com.stackoverflow.q3379797;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {

    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(2);
        Receiver receiver = new Receiver(barrier);
        Sender sender = new Sender(barrier);

        ExecutorService executor = Executors.newFixedThreadPool(2);
        executor.submit(receiver);
        executor.submit(sender);
    }

}

class Receiver implements Runnable {

    private CyclicBarrier barrier;

    public Receiver(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    @Override
    public void run() {
        while (true) {
            try {
                // Wait for ACK (the sleep just simulates that).
                Thread.sleep(2000);
                System.out.println("ACK");

                // Then notify.
                barrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

class Sender implements Runnable {

    private CyclicBarrier barrier;

    public Sender(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    @Override
    public void run() {
        while (true) {
            try {
                // Wait for notify.
                barrier.await();

                // Now do SEND.
                System.out.println("SEND");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

You'll see the following in the stdout:

(2 seconds)
ACK
SEND
(2 seconds)
ACK
SEND
(2 seconds)
ACK
SEND
BalusC
Thank you, excellent answer, just what I was looking for.
fred basset
You're welcome.
BalusC