在Java中使用偶数和奇数线程以自然顺序打印数字

在Java中使用偶数和奇数线程以自然顺序打印数字,java,multithreading,Java,Multithreading,我知道以前有人问过这个问题,但我不明白为什么我的解决方案对我不起作用。我有两个线程偶数和奇数,一个打印偶数,另一个打印奇数。当我启动线程时,我希望输出是自然的数字顺序,比如0 1 2 3..等等。这是我的代码:- [更新] public class ThreadCommunication { public static void main(String... args) throws InterruptedException { final ThreadCommunication o

我知道以前有人问过这个问题,但我不明白为什么我的解决方案对我不起作用。我有两个线程偶数和奇数,一个打印偶数,另一个打印奇数。当我启动线程时,我希望输出是自然的数字顺序,比如0 1 2 3..等等。这是我的代码:- [更新]

public class ThreadCommunication {


public static void main(String... args) throws InterruptedException
{
    final ThreadCommunication obj = new ThreadCommunication();
    Thread even = new Thread(){
        @Override
        public void run()
        {
            for(int i=0;i<10;i=i+2){
                synchronized(obj){
                    System.out.println(i);
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    };
    Thread odd = new Thread(){
        @Override
        public void run()
        {
            for(int i=1;i<10;i=i+2){
                synchronized(obj){
                    System.out.println(i);
                    obj.notify();
                }
            }

        }
    };
    even.start();
    odd.start();
}
我做错了什么?

编辑:

volatile static boolean isAlreadyWaiting = false;



Thread even = new Thread() {
            @Override
            public void run() {
                synchronized (obj) {
                    for (int i = 0; i < 10; i = i + 2) {
                        System.out.println(i);
                        try {
                            if (!isAlreadyWaiting) {
                                isAlreadyWaiting = true;
                                obj.wait();
                            }
                            obj.notify();
                            isAlreadyWaiting=false;

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                }
            }
        };
        Thread odd = new Thread() {
            @Override
            public void run() {
                synchronized (obj) {
                    for (int i = 1; i < 10; i = i + 2) {
                        System.out.println(i);
                        try {
                            if(isAlreadyWaiting){
                            obj.notify();
                            isAlreadyWaiting = false;
                            }
                            if (!isAlreadyWaiting) {
                                isAlreadyWaiting = true;
                                obj.wait();
                            }

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                }
            }
        };

有关所有权的更多信息

此方法(wait或notify)只应由 是此对象监视器的所有者。线程成为的所有者 对象的监视器有以下三种方式之一:

  • 通过执行该对象的同步实例方法
  • 通过执行同步的synchronized语句体 在物体上

  • 对于类类型的对象,通过执行同步静态方法 那一类的

  • 一次只有一个线程可以拥有对象的监视器。@Pragnani Kinnera对您看到的异常是正确的。但是如果您想在
    偶数
    奇数
    之间切换,则需要将第二个同步块移动到循环中。否则,通知线程将以独占方式保持锁,直到循环完成。(与第一个线程相反,第一个线程在每一轮上都会产生锁。)

    Thread奇数=新线程(){
    @凌驾
    公开募捐
    {
    对于(int i=1;i,以下是您的解决方案:

    public class ThreadCommunication {
    
    
        public static void main(String args[]) throws InterruptedException
        {
            final ThreadCommunication obj = new ThreadCommunication();
            Thread even = new Thread("Even Thread"){
                @Override
                public void run()
                {
    
                    for(int i=0;i<10;i=i+2){
                        System.out.println(i);
    
                        synchronized(obj){
    
                            obj.notify();
                        }
                        synchronized(obj){
                            try {
                                obj.wait();
                            }
                            catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
    
                }
    
            };
            Thread odd = new Thread(){
                @Override
                public void run()
                {
    
                    for(int i=1;i<10;i=i+2){
                        try {
                            synchronized(obj){
                                obj.wait();
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(i);
                        synchronized(obj){
                            obj.notifyAll();
                        }
                    }
                }
            };
            even.start();
            odd.start();
        }
    
    }
    
    公共类线程通信{
    公共静态void main(字符串args[])引发InterruptedException
    {
    最终线程通信obj=新线程通信();
    线程偶数=新线程(“偶数线程”){
    @凌驾
    公开募捐
    {
    
    对于(int i=0;i)您的回答帮助我消除了异常,但我仍然无法获得预期的正确输出。我已更新了代码。@Surajhk您应该放置
    try{obj.wait();}catch(InterruptedException e){e.printStackTrace();}
    此代码位于for循环之外,因为您的上一个代码将打印一个偶数,然后偶数线程将等待我期望的输出0123456789@PragnaniKinnera,如果第二个线程首先获得锁,则此代码将死锁。它也不考虑虚假唤醒。将
    1023456789
    作为输出,您将应该强制
    偶数
    线程在
    奇数
    线程之前启动。问题只与每个线程打印的第一个数字有关,它们从
    2
    开始工作正常。编辑:在
    尝试{}catch{}之后移动
    println
    应该足够了。我仍然无法获得一致的预期输出。我已更新了question@Surajhk您的预期输出是什么?
    123456789
    ?我的预期输出是0123456789
    obj.wait();
    
    obj.notify();
    
    Thread odd = new Thread(){
        @Override
        public void run()
        {
    
            for(int i=1;i<10;i=i+2){
                synchronized(obj){
                    System.out.println(i);
                    notify();
                }
            }
        }
    };
    
    public class ThreadCommunication {
    
    
        public static void main(String args[]) throws InterruptedException
        {
            final ThreadCommunication obj = new ThreadCommunication();
            Thread even = new Thread("Even Thread"){
                @Override
                public void run()
                {
    
                    for(int i=0;i<10;i=i+2){
                        System.out.println(i);
    
                        synchronized(obj){
    
                            obj.notify();
                        }
                        synchronized(obj){
                            try {
                                obj.wait();
                            }
                            catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
    
                }
    
            };
            Thread odd = new Thread(){
                @Override
                public void run()
                {
    
                    for(int i=1;i<10;i=i+2){
                        try {
                            synchronized(obj){
                                obj.wait();
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(i);
                        synchronized(obj){
                            obj.notifyAll();
                        }
                    }
                }
            };
            even.start();
            odd.start();
        }
    
    }