在两个线程之间交替(生产者 - 消费者)

时间:2015-12-13 11:41:51

标签: java

我尝试编辑我的程序,以便交替调用incrementerdecrementer类,首先执行incrementer。我的目标是能够在每个sharedValue / increment之后打印共享变量(decrement)的值,并希望看到它在1和{{1}之间切换}。以下是我的0课程的代码,main课程和semaphore课程(有一个课程incrementer,其样式与decrementer相同,所以我没有把它包括在内。)

主要班级

icrementer

信号量类

public class Main extends Thread {

    private static int sharedValue = 0;
    private static Semaphore semaphore = new Semaphore(1);
    static int numberOfCycles = 20000;

    public static void increment() {
        semaphore.down();
        sharedValue++;
        semaphore.up();
    }

    public static void decrement() {
        semaphore.down();
        sharedValue--;
        semaphore.up();
    }

    public static void main(String[] args) throws InterruptedException {

        incrementer inc = new incrementer(numberOfCycles);
        inc.start();
        inc.join();

        decrementer dec = new decrementer(numberOfCycles);
        dec.start();
        dec.join();

        System.out.println(sharedValue);
    }
}

增加类

private int count;
// Constructor
public Semaphore(int n) {
    count = n;
}

// Only the standard up and down operators are allowed.
public synchronized void down() {

    while (count == 0) {

        try {
            wait(); // Blocking call.
        } catch (InterruptedException exception) {
        }
    }
    count--;
}

public synchronized void up() {
    count++;
    notify(); 
}

提前致谢!

所以我一直在阅读我的笔记,我发现我可以使用另一个互斥信号量,它可以确定缓冲区是满还是空。我采用这种方法是对的吗?

1 个答案:

答案 0 :(得分:1)

Thread.Join导致主线程等待增量器的完成,然后启动减量器,然后等待减量器完成。如果您希望它们同时运行,请删除两个Thread.Join调用:

public static void main(String[] args) throws InterruptedException {
    incrementer inc = new incrementer(numberOfCycles);
    decrementer dec = new decrementer(numberOfCycles);

    inc.start();
    dec.start();
}

要在每次递增或递减后打印共享值,请将 println 调用移至主类的增量减量函数:

public static void increment() {
    semaphore.down();
    sharedValue++;
    System.out.println(sharedValue);
    semaphore.up();
}


public static void decrement() {
    semaphore.down();
    sharedValue--;
    System.out.println(sharedValue);
    semaphore.up();
}

另请注意,即使进行了这些更改,您也不会观察到1和0之间的切换。这是因为两个线程不会同时启动,即使它们已经完成(例如使用CyclicBarrier)您无法控制日程安排,因此他们的进度会有所不同。如果你真的想观察这个输出,你应该让每个线程在调用semaphore.up()之前和之后等待1ms,以便让另一个线程有机会等待并从信号量中获取许可。

public static void increment() {
    semaphore.down();
    sharedValue++;
    System.out.println(sharedValue);

    try {
        Thread.sleep(1); //give time to other threads to wait for permit
        semaphore.up();
        Thread.sleep(1); //give time to other threads to acquire permit
    } catch (InterruptedException ex) {
    }
}

有更强大的方法可以从两个线程获得此类输出,但我不想对您的代码进行重大修改。