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

在服务于套接字连接的两个线程之间共享公共数据

龙昊焱
2023-03-14
    null

我所尝试的:(我想是愚蠢的)

  • 我有一个public类,该对象应该作为public static共享,这样我就可以将其作为全局使用,而无需实例化它,例如MyGlobalClass.SharedMsg.
  • 这不起作用,我无法将在一个线程中接收到的数据发送到另一个线程。

我知道有一个明显的锁定问题,因为如果一个线程正在写一个对象,其他线程不能访问它,直到第一个线程完成了写。

// Method of server class
public void startServer()
{
    if (!isRunning)
    {
        try
        {
            isRunning = true;
            while (isRunning)
            {
                try
                {
                    new ClientHandler(mysocketserver.accept()).start();
                }
                catch (SocketTimeoutException ex)
                {
                    //nothing to perform here, go back again to listening.
                }
                catch (SocketException ex)
                {
                    //Not to handle, since I'll stop the server using SocketServer's close() method, and its going to throw SocketException anyway.
                }
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
    else
        System.out.println("Server Already Started!");
}

ClientHandler类。

public class ClientHandler extends Thread
{
    private Socket client = null;
    private ObjectInputStream in = null;
    private ObjectOutputStream out = null;

    public ClientHandler(Socket client)
    {
        super("ClientHandler");
        this.client = client;
    }

    //This run() is common for every Client that connects, and that's where the problem is.
    public void run()
    {
        try
        {
            in = new ObjectInputStream(client.getInputStream());
            out = new ObjectOutputStream(client.getOutputStream());

            //Message received from this thread.
            String msg = in.readObject().toString();
            System.out.println("Client @ "+ client.getInetAddress().getHostAddress() +" Says : "+msg);


            //Response to this client.
            out.writeObject("Message Received");

            out.close();
            in.close();
            client.close();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
}

我认为,我创建动态线程来为每个连接的客户机服务的方式(共享相同的数据源)不可能使用Global object,因为上面的run()对每个连接的客户机都是完全相同的,因此这个方法既是使用者也是生产者。我应该做什么修复,这样我就可以为每个连接创建动态线程,并仍然共享相同的对象。

共有1个答案

许学真
2023-03-14

您可能需要每个客户端之间的通信队列。每个队列将是数据从一个客户机推送到另一个客户机的“管道”。

您可以这样使用它(伪代码):

Thread 1:
Receive request from Client A, with message for Client B
Put message on back of concurrent Queue A2B
Respond to Client A.

Thread 2:
Receive request from Client B.
Pop message from front of Queue A2B
Respond to Client B with message.

您可能还希望它是通用的,因此您有一个AllToB队列,许多客户机(因此也有许多线程)可以写入该队列。

    null

1的例子:

public class ClientHandler extends Thread
{
  public static final Map<ClientHandler, BlockingQueue<String>> messageQueues 
    = new ConcurrentHashMap<>();

  <snip>

  public ClientHandler(Socket client)
  {
    super("ClientHandler");
    this.client = client;
    // Note: Bad practice to reference 'this' in a constructor.
    // This can throw an error based on what the put method does.
    // As such, if you are to do this, put it at the end of the method.
    messageQueues.put(this, new ArrayBlockingQueue<>());
  }

  // You can now access this in the run() method like so:
  // Get messages for the current client.
  // messageQueues.get(this).poll();
  // Send messages to the thread for another client.
  // messageQueues.get(someClient).offer(message);

几个注意事项:

  • messageQueues对象应该真正包含客户端的某种标识符,而不是短期的对象引用。
  • 可测试性更强的设计将messageQueues对象传递到构造函数中以允许模拟。
  • 我可能建议为映射使用包装器类,这样您就可以使用2个参数调用offer,而不必担心映射语义。
 类似资料:
  • 我有大约60个套接字和20个线程,我想确保每个线程每次都在不同的套接字上工作,所以我根本不想在两个线程之间共享同一个套接字。 在我的类中,我有一个后台线程,它每60秒运行一次并调用方法。在方法中,我迭代我拥有的所有套接字,然后通过调用类的方法开始逐个ping它们,并根据响应将它们标记为活的或死的。在方法中,我总是需要迭代所有套接字并ping它们以检查它们是活的还是死的。 现在,所有读取器线程将并发

  • 问题内容: 有没有办法在AngularJS中的服务之间共享数据? 用例:来自不同服务的数据聚合 例如,我想要一个service1从REST服务加载一些数据。然后,另一个service2将来自另一个REST API的其他数据添加到service1数据中,以创建数据聚合服务。 我基本上是想根据它们使用的API来分离服务,但是仍然有一个服务来最终保存所有数据。 问题答案: 创建使用延迟库的第三项服务,以

  • 问题内容: 我有两个线程。可以调用修改变量的类的update方法。另一个调用读取该变量的类的update方法。只有一个线程写入,一个(或多个)线程读取该变量。由于我是多线程技术的新手,我需要在并发方面做什么? 谢谢, 问题答案: 如果有且仅有一个写线程,你可以逃脱使得它。否则,请查看答案。 仅在只有一个写线程的情况下才起作用,因为只有一个写线程,因此它始终具有的正确值。

  • 当前体系结构: 问题: 我们在前端和后端层之间有一个两步流程。 null 微服务2(MS2)需要验证I1的完整性,因为它来自前端。如何避免对MS1进行新的查询?最好的办法是什么? 我试图优化的流删除了步骤1.3和2.3 流程1: null 流程2: 2.1用户X已在本地/会话存储中存储了数据(MS2_Data) 2.2用户X在MS1上保留数据(MS2_Data+MS1_Data) 2.3 MS1使

  • 我们希望基于公共字段(主键)执行Kstream Kstream连接。目前,使用下面的代码,我们得到的结果是只合并了两个流,没有任何主键约束。 您能建议如何根据公共字段/列连接2个流吗。

  • 问题内容: 我是Go菜鸟,无法找到在Go中打开mysql连接然后在http处理程序之间共享它的完整示例。到目前为止,这是我的代码,如何使用在HomeHandler中的main()中打开的db连接? 问题答案: 数据库/ sql程序包会自动为您管理连接池。 返回 代表连接池 而不是单个连接的句柄。如果池中的所有连接都忙,则数据库/ sql软件包会自动打开一个新连接。 将其应用于代码意味着,您只需要共