java - Java 套接字的 PrintWriter 线程安全吗?

标签 java multithreading sockets

所以,我有两个线程。

线程一管理客户端连接。 (只有一台客户端和一台服务器)
我称它为我的服务器线程。

线程二管理向客户端发送消息。我称它为我的消息处理器线程。

线程一负责定期向客户端发送心跳。

在编程时,我假设套接字不是线程安全的,但缓冲区是线程安全的,只要我为服务器和处理器线程使用单独的缓冲区就可以了。

我还假设“PrintWriter”类似于 Java 中的套接字缓冲区。

在这些假设下,我编写了这个函数来发送心跳:

public void sendHeartBeat(){
        logger.info("Sending a hearbeat!");
        PrintWriter printWriter=null;
        try {
            printWriter = new PrintWriter(clientSocket.getOutputStream());
        } catch (IOException e) {
            logger.info(e.toString());
        }
        if(printWriter!=null){
            printWriter.print("HEARTBEAT#");
            printWriter.flush();
        }
    }

另一个线程,“处理器”,它做了类似的事情:

printWriter=new PrintWriter(theServer.getClientSocket().getOutputStream());

以这种方式,每次我希望发送心跳时,我都会创建一个新的“缓冲区”,并且我的消息永远不会被覆盖。

不幸的是,情况似乎并非如此。我通过管道收到一条消息,如下所示: dsgdsb心跳#sdg

这会导致稍后出现核心转储。

这是我的问题:

1) 套接字显然不是线程安全的,但是我从它们那里得到的 PrintWriters 是线程安全的吗?还是只是返回相同的 PrintWriter?

2) 什么类似于 Java 中的套接字缓冲区?我该如何思考这个问题?

3) 如何让这些线程不写入套接字上的同一个缓冲区?

最佳答案

将这些多个 PrintWriter 放在同一个流上是一个糟糕的设计。实际上,您至少希望调用它们的对象同步(或线程限制)。

但是,假设出于某种原因您确实需要多个 PrintWriter:

第一个问题:Writer 不使用this 作为锁。 PrintWriterBufferedWriter 默认情况下都使用 Writer 作为锁来构造它们。这显然是彻底崩溃了。他们应该使用 Writer 的锁,而不是 Writer 本身。一个容易犯的错误是锁定 Object 的一个特性会移除静态类型安全。因此,您需要构造一个 PrintWriter,并将套接字 OutputStream(或其他一些常见对象)作为锁。

其次,我们在 PrintWriter 中进行了缓冲。所以缓冲区结束时,一半被写入,一半等待下一次写入。为防止这种情况发生,要么在外部锁定以组合 printflush,要么使用自动刷新并添加换行符。

因此,它不是有意义线程安全的,但您可以破解它。或者您可以使用更好的设计。

关于java - Java 套接字的 PrintWriter 线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/714287/

相关文章:

java - 我可以将 MouseMotionListener 添加到 Java 中的另一个线程吗?

java - com.itextpdf :book:war:5. 3.1-SNAPSHOT:无法解析以下 Artifact :

java - vfs2 DefaultFileMonitor 线程提前终止

c++ - 从多个线程在同一个套接字上发布许多 wsasend

c# - 简单的 C# Metro StreamSocket 示例

javascript - 套接字远程端口代表什么?

java - 如何设计一个简单的 JSP 来管理 ManyToOne Hibernate 关联

java - 运行 Maven 项目 - 目标 'add-maven-repo'

c++ - 如果其他人正在等待,是否有标准的 STL 或 Qt 方法来产生互斥量,否则保留它?

python - python 找不到开放端口