开发者社区> 问答> 正文

java中多个线程调用同一个socket发送消息:报错

一个客户端,线程 Thread1,Thread2 ,Thread3 。。。。使用同一个socket发送消息(消息头+消息体)在每个线程调用这个socket发送消息要不要对其进行枷锁,如果不加锁服务器端收到的消息包会不会乱包?

网上的解决方法是:将所有的线程要发送的消息放进一个队列,再由一个线程不停的循环队列,一有消息则发送。

消息读的问题:当使用架构一时,每次可能会读取到其他消息,从而导致其他线程无法接受到消息,但使用架构二时怎样将读到的消息传递给其他的线程呢?

使用的架构

架构一:ThreadA:write ,read 。ThreadB:write,read。ThreadC:write,read。

架构二:ThreadA:write。ThreadB:write。ThreadC:write。Thread:read。

架构一就是线程发送一个读一个,架构二就是每个线程发送都是独立的,每个消息的接收都是由一个线程接收。

上面哪种要好一些,架构一有什么缺点,架构二有什么缺点,还有没有更好一点的socket编程架构!

展开
收起
kun坤 2020-06-06 23:17:33 1222 0
1 条回答
写回答
取消 提交回答
  • 多线程一般对socket加锁就好了,这是其一。

    其二是针对tcp才需要加锁,udp多线程直接sendto就好了,但不保证到达以及不保证到达顺序。

    ######你先交代下,是tcp还是udp,对于这两种协议,锁的意义是不同的。######socket不就是建立在tcp/ip 层之上的吗?我现在的问题是,socket在发送消息包时,会不会对自身进行加锁,只有当正在发送的消息包发送完之后,其他的线程才能够调用此socket进行数据包的发送?######

    引用来自“郭煜”的答案

    多线程一般对socket加锁就好了,这是其一。

    其二是针对tcp才需要加锁,udp多线程直接sendto就好了,但不保证到达以及不保证到达顺序。

    socket 有两种一种 TCP/IP 一种UDP/IP,   PrintWriter 的输出方法如下已经加锁:
    public void println(String x) {
    	synchronized (lock) {
    	    print(x);
    	    println();
    	}
        }
     ByteArrayOutputStream 的write 方法也已经加锁:
    public synchronized void write(int b) {
     int newcount = count + 1;
     if (newcount > buf.length) {
                buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
     }
     buf[count] = (byte)b;
     count = newcount;
        }
    ######了解了,受用,非常感谢!######

    引用来自“xiaoxia”的答案

    引用来自“郭煜”的答案

    多线程一般对socket加锁就好了,这是其一。

    其二是针对tcp才需要加锁,udp多线程直接sendto就好了,但不保证到达以及不保证到达顺序。

    socket 有两种一种 TCP/IP 一种UDP/IP,   PrintWriter 的输出方法如下已经加锁:
    public void println(String x) {
    	synchronized (lock) {
    	    print(x);
    	    println();
    	}
        }
     ByteArrayOutputStream 的write 方法也已经加锁:
    public synchronized void write(int b) {
     int newcount = count + 1;
     if (newcount > buf.length) {
                buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
     }
     buf[count] = (byte)b;
     count = newcount;
        }
    受用!
    ######

    阻塞和非阻塞是个需要考虑的问题,这个要结合业务需要,如果阻塞的话,如果超时有可能造成成串的time out。

    如果是简单报文的话,何不从报文体入手,加以识别,比如每个报文带一个唯一号,在请求体与返回体上加以识别,这样就不乱了。

    ######好像没有必要吧,数据包不大直接发就行了,前面跟上包头,业务标识等信息,如果是多个数据包手动拆分的,在业务里处理就行了######

    引用来自“左国党”的答案

    好像没有必要吧,数据包不大直接发就行了,前面跟上包头,业务标识等信息,如果是多个数据包手动拆分的,在业务里处理就行了
    但是我读取的时候,根据的是数据包的消息头进行读取的,也是说先读取消息头,然后根据消息头的数据再去读消息体,如果是多个线程同时在读的话,就会引起消息读取的混乱,加锁貌似也无效,只能使用一个线程去读取,然后根据读取的内容传递给不同的线程。不知道还有没有其他的方法!
    ######这就跟多线程写同一个文件是一样的,注意好锁策略就行
    2020-06-08 11:20:20
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载