当前位置: 首页 > 知识库问答 >
问题:

两个线程通过同步的方法访问一个队列;其中一个可以严格优先于另一个吗?

容修贤
2023-03-14

我正在尝试为我的大学网络做一个聊天应用程序。它实际上是两个程序:一个用于服务器,另一个用于客户端。所有客户端消息都将发送到服务器,发送方的名称和预期目标将预先添加到服务器。服务器使用此信息将消息发送给目标。

我写了一个程序,模拟了服务器端的东西,有4个类:模型、消息中心、接收者和发送者。

接收器在独立线程上生成字符串,并通过随机超时将其添加到MessageCentre中的队列中。发件人检查队列是否是空的,如果不是,它会发送消息(只需打印它)。Model类只包含启动Recector和Sender线程的main方法。

这是模拟的代码:

模范班-

package model;

public class Model {
    public static void main(String[] args) {
        Receiver receiver = new Receiver();
        Sender sender = new Sender();
        receiver.start();
        sender.start();
    }
}

信息中心类-

package model;

import java.util.LinkedList;
import java.util.Queue;

public class MessageCentre {
    private static Queue<String> pendingMessages = new LinkedList<>();

    public static synchronized boolean centreIsEmpty() {
        return pendingMessages.isEmpty();
    }

    public static synchronized String readNextAndRemove() {
        return pendingMessages.remove();
    }

    public static synchronized boolean addToQueue(String message) {
        return pendingMessages.add(message);
    }
}

接收级-

package model;

import java.util.Random;

public class Receiver extends Thread {

    private int instance;

    public Receiver() {
        instance = 0; //gets incremented after each message
    }

    @Override
    public void run() {
        while (true) {            
            boolean added = MessageCentre.addToQueue(getMessage());
            if (!added) {
                System.out.println("Message " + instance + " failed to send");
            }
            try {
                //don't send for another 0 to 10 seconds
                Thread.sleep(new Random().nextInt(10_000));                
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    private String getMessage() {
        int copyInstance = instance;
        instance++;

        return "Message " + copyInstance;
    }
}

发件人类别-

package model;

public class Sender extends Thread {
    @Override
    public void run() {
        while(true) {
            if(!MessageCentre.centreIsEmpty()) {
                System.out.println(MessageCentre.readNextAndRemove());
            }
        }
    }
}

问题:如果将接收器类的getMessage()方法替换为从套接字输入流接受消息的方法,是否有可能丢失一些消息?

至关重要的是,所有接收到的消息都要写入队列,这样就不会丢失任何消息。这个模拟似乎运行良好,但我无法测试通过套接字接收大量消息的场景。

我担心可能发生的情况如下:

接收器获取消息并尝试将其写入队列。发件人持有队列以读取和删除其中的项,从而阻止接收者写入最新的消息。接收器最终有机会将当前消息写入队列,但同时进入套接字输入流的新消息将永远丢失。

这种情况可能吗?如果是的话,是否可以通过将接收者的优先级设置为高于发送者来防止?

共有1个答案

夹谷成仁
2023-03-14

一条新消息同时进入套接字输入流,将永远丢失

总是有可能的,但是不太可能有大量被丢弃的请求,除非您的负载很重或者有不必要的大的关键部分。请求被丢弃也是由于您无法控制的因素造成的,因此您的系统无论如何都需要在面对这些因素时保持健壮。

使用java中的队列实现。util。并发而不是在链接列表上手动同步,代码的队列部分应该可以。

 类似资料:
  • 问题内容: public class Deadlock { static class Friend { private final String name; public Friend(String name) { this.name = name; } public String getName() { return this.name; } public synchronized void b

  • 下面是我的代码: 我将再次指出,如果我使用队列而不是优先级队列,那么代码可以工作。如何访问优先级队列的前部?

  • 问题内容: 我在Java中的线程上有些挣扎,我有三个线程- 线程1,线程2和线程3。那些启动时正在执行某些任务,我想通过thread1停止这两个线程。我将thread1放在,然后停止两个线程,但是两个线程的进程仍在运行。你有什么想法吗? 问题答案: 您如何试图阻止他们??警告此方法已弃用。 而是考虑对线程1使用某种标志来与线程2和3通信,它们应该停止。实际上,您可能会使用interrupts。 下

  • 问题内容: 我相信我的问题很简单。我正在做在裸机上安装Kubernetes集群的先决条件。 假设我有: 主 -主机名泊坞DB容器,其被固定第一节点上 从属 -主机名泊坞DB容器,其被固定第二个节点上 我是否可以从群集中的任何容器(应用程序等)与 master 通信,而不管它是否在同一节点上运行? 这是默认行为吗?还是应该做其他的事情? 我假设我需要在YAML或JSON文件中设置参数,以便Kuber

  • 我写了一个启动两个线程的代码片段;一个线程打印所有奇数,而另一个线程打印所有偶数。我使用了内在锁和线程通信命令的组合来实现两个线程的正确交叉。这是我的代码, 以下是我的问题: > 奇数线程在printOdd()函数中执行,而偶数线程在print偶数()函数中执行。我对两个线程都使用一个内在锁;我不明白两个线程怎么能同时存在于各自的同步块中,因为使用了相同的锁。 我从代码中删除了线程通信语句(通知,

  • 我必须得到如下输出: 这是我的密码。没有错误。它以PlusThread开始并打印第一行。然后它将释放锁。之后,MultiplyThread开始运行。它将打印所有行,而不是通知PlusThread。 这是我的输出: