Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java代码-线程相互阻塞_Java_Multithreading - Fatal编程技术网

Java代码-线程相互阻塞

Java代码-线程相互阻塞,java,multithreading,Java,Multithreading,我不熟悉多线程。我正在尝试编写一个有两个线程的程序。一个线程打印奇数,然后使用wait()放弃监视器锁,类似地,另一个线程打印偶数,并在打印数字后放弃锁 我有四节课 Odd.java(打印1-100之间的奇数) 偶数.java(打印1-100之间的偶数) java(具有打印奇数和偶数的逻辑) OEApp.java(启动线程的主类) 问题-我的代码在大多数情况下都按预期工作,即按顺序打印数字1到100。两条线轮流穿。但我注意到有一个bug,有时偶数线程会先调度,然后低于输出 2 ******

我不熟悉多线程。我正在尝试编写一个有两个线程的程序。一个线程打印奇数,然后使用wait()放弃监视器锁,类似地,另一个线程打印偶数,并在打印数字后放弃锁
我有四节课

  • Odd.java(打印1-100之间的奇数)
  • 偶数.java(打印1-100之间的偶数)
  • java(具有打印奇数和偶数的逻辑)
  • OEApp.java(启动线程的主类)
  • 问题-我的代码在大多数情况下都按预期工作,即按顺序打印数字1到100。两条线轮流穿。但我注意到有一个bug,有时偶数线程会先调度,然后低于输出

    2    **********
    1    ###############################
    
    在没有打印任何内容之后,似乎出现了死锁情况。我不知道为什么。请帮助我理解这一点

    public class SomeMaths {
    
        public synchronized void printOdd(){
            for( int i=1;i<=100;i++){
                if(i%2 !=0) {
                    System.out.println(i + "       ###############################");
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                notify();
            }
        }
    
        public synchronized void printEven(){
            for(int i=1;i<=100;i++){
                if(i%2 ==0){
                    System.out.println(i +"    **********");
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                notify();
            }
        }
      }
    


    我相信它是这样运作的:

  • 偶数线程启动,1是奇数,所以它调用notify(不通知任何人),然后2是偶数,所以它打印消息并等待

  • 奇数线程启动,1为奇数,因此它打印消息并等待

  • 没有人可以调用notify,因此两个线程都会永远等待


  • 您使用同步关键字的目的是什么?
    它只能保证您的函数不会同时运行多次

    我假设您希望一个线程通知另一个线程?是这样吗?
    但是如果在等待发生之前调用了通知,该怎么办

    您知道您可以使用调试器来查看每个线程,从而知道每个线程被卡住的位置吗

    请记住,一旦调用了start,您就无法知道哪个线程将有cpu时间

    此外,您正在尝试同步两个线程(通过使用notify/wait机制),但是还有其他机制将被证明更简单(例如,信号灯:每个线程都有自己的信号灯,获取自己的信号灯,并释放另一个信号灯;将每个信号灯初始化为1,它将顺利运行)

    附言:

    • 我被迫发布一个答案,但它应该是一个评论;对不起

    • 为什么要同时使用runnable和thread接口呢?此外,偶数类已经是线程了,所以没有必要再次包装它


    好奇:如果
    偶数
    扩展
    线程
    ,为什么要使用
    新线程(新偶数(sm))
    用另一个线程包装它?我正要问解决方案是什么,但后来意识到问题不要求解决方案,只要求解释原因,所以我加1。“使用synchronize关键字的目的是什么?”首先,在使用
    notify()
    wait()
    时需要它,所以这是一个愚蠢的问题。“为什么同时使用runnable和thread接口?”因为建议实现
    runnable
    ,而不是扩展
    thread
    ,这意味着您将在代码中“使用”这两个接口。请参阅。您对“为什么同时使用runnable和thread接口?"有点奇怪:我没有建议使用这两种方法中的任何一种,但问了使用这两种方法的原因。评论回答说:因为建议实现
    Runnable
    ,然后将其作为
    Thread
    构造函数的参数,也就是说,您将同时使用这两种方法。我同意Runnable是最好的方法,但正如我所说的ned我对线程是新手,我只是在两种方法之间玩。
    public class Odd implements Runnable {
    
        SomeMaths sm;
    
        public Odd(SomeMaths sm){
            this.sm = sm;
        }
        @Override
        public void run(){
           sm.printOdd();
        }
    }
    
    public class Even extends Thread {
    
        SomeMaths sm;
    
        public Even(SomeMaths sm){
            this.sm = sm;
        }
    
        @Override
        public void run(){
            sm.printEven();
        }
    }
    
    public class OEApp {
    
        public static void main(String[] args) {
    
            SomeMaths sm = new SomeMaths();
    
            Thread odd = new Thread(new Odd(sm));
            Thread even = new Thread(new Even(sm));
    
            odd.start();
            even.start();
    
            try {
                odd.join();
                even.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }