Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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-两个线程通过wait()/notify()进行通信,但线程交替运行,线程先获得锁_Java_Multithreading_Synchronization_Synchronized - Fatal编程技术网

Java-两个线程通过wait()/notify()进行通信,但线程交替运行,线程先获得锁

Java-两个线程通过wait()/notify()进行通信,但线程交替运行,线程先获得锁,java,multithreading,synchronization,synchronized,Java,Multithreading,Synchronization,Synchronized,该方案的预期产出是: 平 庞 发出砰的声响 庞 发出砰的声响 庞 然而,它在这两者之间交替 庞 发出砰的声响 等等 问题是,我创建了Ping线程并首先运行它。所以我不知道为什么Pong偶尔会排在第一位 这是我的代码(易于编译)。从本质上讲,它是有效的。我只是不明白为什么有时候它会先打印“Pong”。有人能解释一下为什么会这样吗 // Printer class - will be the object that both threads lock / synchronize onto class

该方案的预期产出是:

平 庞 发出砰的声响 庞 发出砰的声响 庞

然而,它在这两者之间交替

庞 发出砰的声响 等等

问题是,我创建了Ping线程并首先运行它。所以我不知道为什么Pong偶尔会排在第一位

这是我的代码(易于编译)。从本质上讲,它是有效的。我只是不明白为什么有时候它会先打印“Pong”。有人能解释一下为什么会这样吗

// Printer class - will be the object that both threads lock / synchronize onto
class Printer
{
    int numberOfMessages;
    int messageCount;

    // Constructor allowing user to choose how many messages are displayed
    Printer(int numberOfMessages)
    {       
        this.numberOfMessages = numberOfMessages;
        this.messageCount = 0;
    }

    // If more messages are to be printed, print and increment messageCount
    void printMsg(String msg)
    {
        if (messageCount < numberOfMessages)
        {
            System.out.println("[" + msg + "]");            
            ++messageCount;
        }
        else
        {
            System.exit(0);
        }
    }
}

// PingPong thread
class PingPongThread extends Thread
{
    Printer printer;
    String message; 

    public PingPongThread(Printer printer, String message)
    {
        this.printer = printer;
        this.message = message;
        this.start();
    }

    @Override
    public void run()
    {
        while(true)
        {
            synchronized (printer)
            {                   
                // Print message whether it is Ping or Pong
                printer.printMsg(message);

                // Notify
                printer.notify();

                // Wait
                try
                {
                    printer.wait();
                } 
                catch (InterruptedException e)
                {               
                    e.printStackTrace();
                }
            }
        }
    }


}

// Two threads communicate with eachother to alteratively print out "Ping" and "Pong"
public class PingPong
{
    public static void main(String args[])
    {
        Printer printer = new Printer(6);

        PingPongThread pingThread = new PingPongThread(printer, "Ping");
        PingPongThread pongThread = new PingPongThread(printer, "Pong");
    }
}
//打印机类-将是两个线程锁定/同步到的对象
类打印机
{
int numberOfMessages;
int-messageCount;
//构造函数,允许用户选择显示多少条消息
打印机(int numberOfMessages)
{       
this.numberOfMessages=numberOfMessages;
this.messageCount=0;
}
//如果要打印更多消息,请打印并增加messageCount
无效打印消息(字符串消息)
{
if(messageCount
因为
run
方法在不同的线程中运行,除非进行了适当的同步,否则无法假定哪个线程将首先运行。如果线程先开始,并不意味着它会更重要。所有动物都是平等的


您应该在线程中创建一个特殊的标志,当线程启动时会收到通知。并在启动第二个线程之前等待标志。做这件事的简单方法是使用。

因为
run
方法在不同的线程中运行,除非进行了适当的同步,否则您无法假定哪个线程将首先运行。如果线程先开始,并不意味着它会更重要。所有动物都是平等的


您应该在线程中创建一个特殊的标志,当线程启动时会收到通知。并在启动第二个线程之前等待标志。执行此操作的简单方法是使用。

您希望强制线程按顺序运行。JVM不能保证这一点,因此您必须自己动手。我可以想出两种解决办法

丑陋的黑客,但可能会工作:在启动第一个线程之后,但在启动第二个线程之前,产生当前线程,以“鼓励”它运行。例如:

PingPongThread pingThread = new PingPongThread(printer, "Ping");
Thread.yield();
PingPongThread pongThread = new PingPongThread(printer, "Pong");
这是最简单的解决方案,但不能保证每次都能正常工作,例如,如果另一个线程(比如,事件处理程序)在屈服后抓住控件

更健壮的方法是:让主线程在启动第二个线程之前等待其他信号。假设该信号通过一个名为
lock
的字段传递,这将类似于:

Object lock = new Object();
PingPongThread pingThread = new PingPongThread(lock, printer, "Ping");
lock.wait();
PingPongThread pongThread = new PingPongThread(lock, printer, "Pong");
线程
run()
方法如下

synchronize (lock) { lock.notify(); }
while (true) {
  // As before...
}

您想强制线程按顺序运行。JVM不能保证这一点,因此您必须自己动手。我可以想出两种解决办法

丑陋的黑客,但可能会工作:在启动第一个线程之后,但在启动第二个线程之前,产生当前线程,以“鼓励”它运行。例如:

PingPongThread pingThread = new PingPongThread(printer, "Ping");
Thread.yield();
PingPongThread pongThread = new PingPongThread(printer, "Pong");
这是最简单的解决方案,但不能保证每次都能正常工作,例如,如果另一个线程(比如,事件处理程序)在屈服后抓住控件

更健壮的方法是:让主线程在启动第二个线程之前等待其他信号。假设该信号通过一个名为
lock
的字段传递,这将类似于:

Object lock = new Object();
PingPongThread pingThread = new PingPongThread(lock, printer, "Ping");
lock.wait();
PingPongThread pongThread = new PingPongThread(lock, printer, "Pong");
线程
run()
方法如下

synchronize (lock) { lock.notify(); }
while (true) {
  // As before...
}

JVM不保证线程将按照启动顺序启动。这就是为什么有时第二个线程首先启动。

JVM不能保证线程按照启动顺序启动。这就是为什么有时第二个线程首先启动。

如果创建两个线程,例如
t1
t2
,然后调用:

t1.start();
t2.start();

这并不意味着
t1
将在
t2
之前开始执行。可能是这样,但有可能
t2
会首先启动。您必须编写自己的方法,保证首先从
t1
开始。例如,在启动第一个线程后,如果您创建了两个线程(例如
t1
t2
),则在对象上的
wait()
run()

的开头在该对象上的第一个线程
notify()
中,然后调用:

t1.start();
t2.start();
这并不意味着
t1
将在
t2
之前开始执行。可能是这样,但有可能
t2
会首先启动。您必须编写自己的方法,保证首先从
t1
开始。例如,启动后