为了账号安全,请及时绑定邮箱和手机立即绑定

线程问题 - 接收方在发送方之前打印

线程问题 - 接收方在发送方之前打印

12345678_0001 2024-01-28 20:28:35
我试图找出 java 中的线程,并试图理解我得到的输出。我创建了 3 个类:发送者、接收者和消息框。我正在尝试通过消息框将数据从发送者发送到接收者。当发送方发送数据时,它会打印“发送方放置元素”。一旦接收者获得一个元素,它就会打印“接收者获得元素”问题是,在控制台中,我看到接收者打印出他在发送者打印出他发送了该元素之前获得了该元素。发件人:public class Sender implements Runnable {    private MessageBox msgBox;    public Sender(MessageBox m)    {        msgBox=m;    }    public void run()    {        Thread.currentThread().setName("Sender");        for(int i=0;i< 100;i++)        {            msgBox.put(i);            System.out.println("Sender put element : " + i);            try {                long sleep_time = (long)(Math.random()*5000);                //System.out.println("Sender going to sleep for " + sleep_time + " ms");                Thread.sleep(sleep_time);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}接收者 :public class Receiver implements Runnable{    private MessageBox<Integer>  msgBox;    public Receiver(MessageBox<Integer>m)    {        msgBox = m;    }    public void run()    {        Thread.currentThread().setName("Receiver");        while(true)        {                int element = msgBox.get();                System.out.println("Receiver got element : " + element);            try            {                long sleep_time = (long)(Math.random()*5000);                //System.out.println("Receiver going to sleep for " + sleep_time + " ms");                Thread.sleep(sleep_time);            }            catch (InterruptedException e)            {                e.printStackTrace();            }        }    }}
查看完整描述

2 回答

?
莫回无

TA贡献1865条经验 获得超7个赞

你的代码没问题。您看到的输出可能会发生,因为插入到 messageBox 并打印消息不是原子的。


您在 Sender 中的代码可以像这样被拦截:


  Sender Thread                              Receiver Thread


   msgBox.put(i);

                                             int element =  msgBox.get();

                                            System.out.println("Receiver got element : " + element);  

   System.out.println("Sender put element : " + i);

因此,在发送者放置元素之后和发送者打印消息之前,接收者能够首先获取该元素并打印消息,因为它在另一个线程中运行。在发送者将元素放入 messageBox 之前放置消息没有帮助,因为这样它可能会以另一种方式不一致:它打印元素已添加的消息,但由于某些原因不必实际添加例外。


如果您确实想有序地放置/接收消息,则必须将该消息放入 MessogeBox 方法中,如下所示:


public synchronized void put(E i)

    {

        msgQ.add(i);

        System.out.println("Sender put element : " + i);

        notify();

        System.out.println(Thread.currentThread().getName() + " : notifying other threads...");


    }




public synchronized E get()

{

    if(msgQ.isEmpty())

    {

        try

        {

            System.out.println(Thread.currentThread().getName() + " : waiting for new element..");

            notify();

            wait();

        }

        catch (InterruptedException e)

        {

            e.printStackTrace();

        }

    }


    return msgQ.remove();

}

如果您仅在同步锁下访问 msgQ,则不必将 msgQ 设置为易失性。您还必须将 isEmpty 方法设置为同步,然后不必将 msgQ 设置为易失性。所以像这样修复你的代码:


  public synchronized boolean isEmpty()

    {

        return msgQ.isEmpty();

    }


查看完整回答
反对 回复 2024-01-28
?
智慧大石

TA贡献1946条经验 获得超3个赞

从 Sender 类更新您的打印语句

msgBox.put(i);
System.out.println("Sender put element : " + i);
System.out.println("Sender put element : " + i);
msgBox.put(i);

因为在您的情况下, MessageBox 放置了值,然后 Receiver 突然收到消息并打印,然后您的 print statementent 调用System.out.println("Sender put element : " + i);


查看完整回答
反对 回复 2024-01-28
  • 2 回答
  • 0 关注
  • 92 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信