简体   繁体   English

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

[英]Printing Odd and Even number using 2 threads?

I have tried this code. 我已经尝试过此代码。 But after printing 0 , it doesn't print anything. 但是在打印0之后,它什么也不会打印。 It is blocking due to some lock I think. 由于某些锁定,它正在阻塞。

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

My TestClass: 我的TestClass:

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

Where am I wrong? 我哪里错了? Thank. 谢谢。

PS : I know this type of question has been asked many times , but I want to try by my own. PS:我知道这类问题已经问过很多次了,但我想自己尝试一下。

My guesses is you are; 我的猜测是你是。

  • using one Runnable but both of then think they are even ie they both see the first value of 0 使用一个Runnable,但是两者都认为它们是偶数,即它们都看到第一个值0
  • printEven has to wait for an odd number ad printOdd has to wait for an even number printEven必须等待一个奇数广告printOdd必须等待一个偶数

EDIT: After running the code the OP fixed the code, it prints 编辑:运行代码后,OP修复了代码,它会打印

0
1

as expected. 如预期的那样。 It may sometimes print 0 and 0 randomly as the first check for odd/even is not synchronized. 有时可能会随机打印0和0,因为第一次检查奇数/偶数不同步。

It's a simple deadlock: 这是一个简单的僵局:

Thread 1 waits for someone to notify on the lock. 线程1等待有人通知锁。 Thread 2 waits for someone to notify on the same lock. 线程2等待有人通知相同的锁。

Since no one ever gets to o.notify(); 由于没有人去过o.notify(); , nothing happens. , 什么都没发生。

And i is 0 when both threads start, so both first call printEven() . 当两个线程都启动时, i为0,因此都先调用printEven() Now when that has happened, both threads will then call printOdd() in the next round. 现在,当发生这种情况时,两个线程将在下一轮调用printOdd()

The basic concept is when one thread is running, the other has to wait. 基本概念是当一个线程正在运行时,另一个线程必须等待。 Once the thread prints the value, it has to wait until the other thread prints. 一旦线程打印了值,它就必须等到另一个线程打印出来。 This is achieved by using wait/notify mechanism. 这是通过使用等待/通知机制来实现的。

When Odd thread completes printing the value, it notifies the waiting thread(Even thread) and the Even thread becomes ready to run but will wait for the lock to be released by the Odd thread. 当奇数线程完成打印值时,它将通知等待线程(偶数线程),并且偶数线程准备就绪,可以运行,但将等待奇数线程释放锁定。 Now the odd thread calls wait on the locker object so that it releases the lock and goes to wait state. 现在,奇数线程调用在更衣室对象上等待,以便它释放锁并进入等待状态。 At this point, the only thread waiting for locker object's lock is Even thread and it runs. 在这一点上,唯一等待锁对象锁定的线程是偶数线程并且它正在运行。 This process continues alternatively. 此过程将继续进行。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM