使用2个线程打印奇数和偶数?

时间:2013-09-03 14:37:04

标签: java multithreading locking synchronized runnable

我试过这段代码。但是在打印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();
            }
        }
    }
}

我的TestClass:

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

我哪里错了? 感谢。

P.S:我知道很多次都会问这类问题,但我想亲自尝试。

3 个答案:

答案 0 :(得分:1)

我的猜测是你;

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

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

0
1

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

答案 1 :(得分:0)

这是一个简单的僵局:

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

由于没有人到达o.notify();,所以没有任何事情发生。

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

答案 2 :(得分:0)

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

当奇数线程完成打印值时,它会通知等待线程(偶数线程)并且偶数线程已准备好运行,但将等待奇数线程释放锁定。现在奇数线程调用等待锁定器对象,以便它释放锁并进入等待状态。此时,等待锁定对象锁定的唯一线程是Even thread并且它会运行。这个过程可以继续。

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