0

我试过这段代码。但是在打印 0 之后,它什么也不打印。由于我认为有一些锁,它被阻塞了。

public class EvenOdd implements Runnable {
    private Object o = new Object();
    private volatile int i = 0;

    public void run() {
        try {
            System.out.println();
            if ( Thread.currentThread().getName().equals( "Even")) {
                printEven();
            } else {
                printOdd();
            }
        } catch ( Exception ee) {
            ee.printStackTrace();
        }
    }

    private void printEven() throws InterruptedException {
        while ( true) {
            synchronized ( o) {
                while ( this.i % 2 == 0) {
                    o.wait();
                }
                System.out.println( Thread.currentThread().getName() + i);
                i++;
                o.notify();
            }
        }
    }

    private void printOdd() throws InterruptedException {
        while ( true) {
            synchronized ( o) {
                while ( this.i % 2 != 0) {
                    o.wait();
                }
                System.out.println( Thread.currentThread().getName() + i);
                i++;
                o.notify();
            }
        }
    }
}

我的测试课:

EvenOdd x = new EvenOdd();
        new Thread(x,"Even").start();
        new Thread(x,"Odd").start();

我哪里错了?感谢。

PS:我知道这种问题已经被问过很多次了,但我想自己尝试一下。

4

3 回答 3

1

我猜你是;

  • 使用一个 Runnable 但两者都认为它们是偶数,即它们都看到第一个值 0
  • printEven 必须等待奇数 ad printOdd 必须等待偶数

编辑:运行代码后,OP修复了代码,它打印

0
1

正如预期的那样。它有时可能会随机打印 0 和 0,因为第一次检查奇数/偶数不同步。

于 2013-09-03T14:41:04.860 回答
0

这是一个简单的死锁:

线程 1 等待某人通知锁。线程 2 等待某人通知同一个锁。

由于没有人到达o.notify();,所以什么也没有发生。

并且i在两个线程都启动时为 0,因此都首先调用printEven(). 现在,当这种情况发生时,两个线程都将printOdd()在下一轮调用。

于 2013-09-03T14:48:07.970 回答
0

基本概念是当一个线程正在运行时,另一个必须等​​待。一旦线程打印了值,它必须等到另一个线程打印。这是通过使用等待/通知机制来实现的。

当奇数线程完成打印值时,它会通知等待线程(偶数线程),偶数线程准备好运行,但将等待奇数线程释放锁。现在奇数线程调用 locker 对象上的 wait 以便它释放锁并进入等待状态。此时,唯一等待locker对象锁的线程是Even线程并且它运行。该过程交替地继续。

public class Test {
    public static void main(String[] args) {
        Object locker = new Object();
        Thread t1 = new Thread(new OddWorker(locker));
        Thread t2 = new Thread(new EvenWorker(locker));
        t1.start();
        t2.start();

    }
}

class OddWorker implements Runnable {
    private Object locker;
    private int number = 1, count = 1;

    OddWorker(Object locker) {
        this.locker = locker;
    }

    @Override
    public void run() {
        synchronized (locker){
            do {
                try {
                    System.out.println(Thread.currentThread().getName() + ": " + number);
                    number += 2;
                    locker.notify();
                    locker.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } while(++count < 11);
            locker.notify();
        }
    }
}

class EvenWorker implements Runnable {
    private Object locker;
    private int number = 2, count = 1;

    EvenWorker(Object locker) {
        this.locker = locker;
    }

    @Override
    public void run() {
        synchronized (locker){
            do {
                try {
                    System.out.println(Thread.currentThread().getName() + ": " + number);
                    number += 2;
                    locker.notify();
                    locker.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } while(++count < 11);
        }
    }
}
于 2014-04-04T11:49:18.843 回答