Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.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_Synchronization - Fatal编程技术网

Java线程无法同步

Java线程无法同步,java,multithreading,synchronization,Java,Multithreading,Synchronization,我刚开始使用notify、synchronized和wait,它几乎可以工作,但只有当我让第二个线程sleep()保持1毫秒时,它才能工作。最后你可以看到我的控制台输出 我的主要意见是: public static void main(String[] args) { InfoPaket paket = new InfoPaket(); TestThread testThread = new TestThread(paket); TestThread2 testThre

我刚开始使用notify、synchronized和wait,它几乎可以工作,但只有当我让第二个线程sleep()保持1毫秒时,它才能工作。最后你可以看到我的控制台输出

我的主要意见是:

public static void main(String[] args) {

    InfoPaket paket = new InfoPaket();
    TestThread testThread = new TestThread(paket);
    TestThread2 testThread2 = new TestThread2(paket);
}
我的“锁”类

我的两个测试线程

一,

二,

等等

但是把2。线程每次睡眠都会减慢程序的速度, 但如果没有它,我会有一些奇怪的事情,我无法向自己解释:

waiting
here  1
he got it... lelaoao  1
he got it... lelaoao  2
waiting
here  2
here  3
he got it... lelaoao  3
he got it... lelaoao  4
waiting
here  4
here  5
here  6
here  7
here  8
here  9
here  10
he got it... lelaoao  5
he got it... lelaoao  6
waiting

你的代码按预期工作(按编码),除了-1)你有一些坏代码2)你可能误解了这个概念

首先让我说一下您的代码在做什么:

  • 您有一个
    InfoPaket
    ,它在两个线程之间共享,并保存有关数据包的信息,并跟踪是否收到新信息
  • 然后你有
    TestThread
    ,它将检查是否收到新信息,如果没有收到新信息,它将等待,一旦收到新信息,你将打印信息(始终为“lelaao”)以及循环计数器,就像这样
    他得到了它。。。乐老奥23
  • 然后有
    TestThread2
    ,它将设置信息并通知等待的线程,然后像这样打印该线程的循环计数器-
    “here”+i
  • 现在,最重要的是线程调度是意外的,取决于底层的OS线程调度机制以及JVM实现,因此您不能期望如果线程2设置了信息,那么线程1肯定会执行,您可以尝试执行它,将
    thread.sleep(1)
    Thread.yeild()
    请注意
    Thread.yeild()
    不可移植
    ,最好不要使用它,也不要使用它,而应该使用
    Thread.sleep(1)

    现在,让我们来看看糟糕的代码和一些重要的概念:

    错误代码
  • 您所做的最错误的事情是从构造函数启动一个新线程,永远不要尝试从构造函数启动一个新线程,因为它会导致您的引用在构造函数完成之前泄漏。阅读
  • 您不需要在
    TestThread2
    中引用当前线程,因为您可以直接执行
    thread.sleep(1)将导致当前线程休眠
  • 您正在打印
    System.out.println(“他知道了…”+info+“”+i)
    系统输出打印项次(“此处”+i)来自主线程,但是您应该从同步块打印这些,以确保没有交错,因为在没有同步的情况下,可能会发生交错,您可以看到
    他得到了它。。。Lelaao 3
    之前的
    这里的3
    在逻辑上是错误的
  • 现在,下面是固定的代码,它将产生正确的结果(考虑到您正在给线程1一个机会,一旦线程2设置了信息就可以运行),输出也放在了最后

    InfoPaket.java

    public class InfoPaket {
    
        String info;
        char infoDataSign;
        boolean newInfo = false;
    
        public synchronized boolean isNew() {
            if (!newInfo) {
                try {
                    System.out.println("waiting");
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return newInfo;
        }
    
        public synchronized void getInfo(int i) {
            newInfo = false;
            System.out.println("he got it... " + info + "  " + i);
        }
    
        public synchronized void setInfo(String info, int i) {
            this.info = info;
            newInfo = true;
            System.out.println("here  " + i);
            notify();
        }
    
        public static void main(String[] args) {
    
            InfoPaket paket = new InfoPaket();
            TestThread testThread = new TestThread(paket);
            TestThread2 testThread2 = new TestThread2(paket);
    
            new Thread(testThread, "testThread").start();
            new Thread(testThread2, "testThread2").start();
        }
    }
    
    public class TestThread implements Runnable {
    
        InfoPaket info;
        int i = 0;
    
        public TestThread(InfoPaket info) {
            this.info = info;
        }
    
        public void run() {
            while (true) {
                i++;
                getInfo(i);
            }
        }
    
        void getInfo(int i2){
             info.isNew();
             info.getInfo(i2);
        }
    }
    
    public class TestThread2 implements Runnable {
    
        InfoPaket info;
        int i = 0;
    
        public TestThread2(InfoPaket info) {
            this.info = info;
        }
    
        public void run() {
            while (i < 500000) {
                i++;
                setInfo(i);
            }
        }
    
        void setInfo(int i2) {
    
            info.setInfo("lelaoao", i2);
    
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    } 
    
    TestThread.java

    public class InfoPaket {
    
        String info;
        char infoDataSign;
        boolean newInfo = false;
    
        public synchronized boolean isNew() {
            if (!newInfo) {
                try {
                    System.out.println("waiting");
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return newInfo;
        }
    
        public synchronized void getInfo(int i) {
            newInfo = false;
            System.out.println("he got it... " + info + "  " + i);
        }
    
        public synchronized void setInfo(String info, int i) {
            this.info = info;
            newInfo = true;
            System.out.println("here  " + i);
            notify();
        }
    
        public static void main(String[] args) {
    
            InfoPaket paket = new InfoPaket();
            TestThread testThread = new TestThread(paket);
            TestThread2 testThread2 = new TestThread2(paket);
    
            new Thread(testThread, "testThread").start();
            new Thread(testThread2, "testThread2").start();
        }
    }
    
    public class TestThread implements Runnable {
    
        InfoPaket info;
        int i = 0;
    
        public TestThread(InfoPaket info) {
            this.info = info;
        }
    
        public void run() {
            while (true) {
                i++;
                getInfo(i);
            }
        }
    
        void getInfo(int i2){
             info.isNew();
             info.getInfo(i2);
        }
    }
    
    public class TestThread2 implements Runnable {
    
        InfoPaket info;
        int i = 0;
    
        public TestThread2(InfoPaket info) {
            this.info = info;
        }
    
        public void run() {
            while (i < 500000) {
                i++;
                setInfo(i);
            }
        }
    
        void setInfo(int i2) {
    
            info.setInfo("lelaoao", i2);
    
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    } 
    
    TestThread2.java

    public class InfoPaket {
    
        String info;
        char infoDataSign;
        boolean newInfo = false;
    
        public synchronized boolean isNew() {
            if (!newInfo) {
                try {
                    System.out.println("waiting");
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return newInfo;
        }
    
        public synchronized void getInfo(int i) {
            newInfo = false;
            System.out.println("he got it... " + info + "  " + i);
        }
    
        public synchronized void setInfo(String info, int i) {
            this.info = info;
            newInfo = true;
            System.out.println("here  " + i);
            notify();
        }
    
        public static void main(String[] args) {
    
            InfoPaket paket = new InfoPaket();
            TestThread testThread = new TestThread(paket);
            TestThread2 testThread2 = new TestThread2(paket);
    
            new Thread(testThread, "testThread").start();
            new Thread(testThread2, "testThread2").start();
        }
    }
    
    public class TestThread implements Runnable {
    
        InfoPaket info;
        int i = 0;
    
        public TestThread(InfoPaket info) {
            this.info = info;
        }
    
        public void run() {
            while (true) {
                i++;
                getInfo(i);
            }
        }
    
        void getInfo(int i2){
             info.isNew();
             info.getInfo(i2);
        }
    }
    
    public class TestThread2 implements Runnable {
    
        InfoPaket info;
        int i = 0;
    
        public TestThread2(InfoPaket info) {
            this.info = info;
        }
    
        public void run() {
            while (i < 500000) {
                i++;
                setInfo(i);
            }
        }
    
        void setInfo(int i2) {
    
            info.setInfo("lelaoao", i2);
    
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    } 
    
    需要明确的重要概念 我认为您可能缺少一些概念,所以您认为输出是疯狂的

  • 一旦您使用线程2设置了信息,就不能保证线程1会运行,因为线程调度是意外的,并且取决于底层操作系统线程调度机制以及JVM实现,我在
    thread.yield()
    thread.sleep()
    开头强调了关于这一点的更多内容。注意,如果您不使用
    Thread.sleep(1)
    ,那么您就不能期望输出是一致的,正如我在下面所示
  • 当您执行
    Thread.sleep
    时,如果该线程正在获取一些锁,那么它不会释放锁
  • 一旦你做了
    notify()
    那么您不能期望等待的线程立即“可运行”,并且获取锁的线程不会在
    notify()时立即释放锁时,只有在同步块/方法完成后才会释放锁
  • 如果您在第二个线程中没有执行
    Thread.sleep(1)
    ,那么您就不能期望一致的输出,以及我上面解释的原因

  • OP评论:


    你知道有什么更有效的方法从网上传送数据吗 把线接到另一个


    您拥有“共享内存”或“消息传递”;在这种情况下,共享内存就是我们正在做的事情,如果你想进行消息传递,那么你可以使用Java API,比如阻塞队列()实现,但这完全是另一回事。

    “但是每次休眠2.线程都会减慢程序的速度。但是如果没有消息传递,我就无法向自己解释一些疯狂的事情。”..线程应表现良好。线程1不睡眠也不等待,因为get info方法也不等待,所以您具有失控线程的特性。线程化所节省的时间必须大于与线程化相关的成本synchronization@RajeevRanjan更好吗?=)@什么是T台线程?为什么不等待呢?因为它会打印“等待”?看看线程1。循环不睡眠。它调用getInfo,它只做一件事:获取新信息。当线程2休眠时,线程1可以在一毫秒内执行几百次。如果这对你有帮助,我将把它作为一个答案发布。非常感谢你的代码和解释=)你还没有发现OP代码中的所有错误。睡眠应该是不必要的。你知道有什么更有效的方法将数据从一个线程传输到另一个线程吗?@NathanHughes Sleeping(1毫秒)让thread1在没有
    线程的情况下运行。睡眠(1)
    的情况下,t1或t2是否运行完全不确定