这里有个套接字类,用于发送消息,我使用了一个 List 来储存消息,然后用一个无线循环来发送消息,首先每个消息都设为一个类
public class SocketMsg{
public String ip;
public int port;
public byte[] msg;
};
然后我在某个单例类里有一个 List<SocketMsg>来储存要发送的消息,该类由一个函数,添加消息,整个程序都会用通过这个函数添加消息,类似下面的代码
public MyUdpSocket{
private MyUdpSocket mySocket = null;
public static MyUdpSocket getInstance(){
if(mySocket == null)
mySocket = new MyUdpSocket();
};
private List<SocketMsg> msgQueue = new AtrrayList<>();
public addMsgToQueue(SocketMsg msg){
msgQueque.add(msg);
};
};
然后这个 MyUdpSocket 类里还有个内部类,该类继承 Thread,类似下面代码
private class SendThread extends Thread {
private SendThread() {
}
@Override
public void run() {
while (true) {
if (udpSocket == null || udpSocket.isClosed()) {return;}
if(msgQueue.size() == 0) continue;
try {
SendMsg sendMsg = msgQueue.get(0);
InetAddress devAddress = InetAddress.getByName(sendMsg.IP);
DatagramPacket mDatagram = new DatagramPacket(sendMsg.Msg, sendMsg.Msg.length, devAddress, sendMsg.Port);
udpSocket.send(mDatagram);
msgQueue.remove(0); //唯一的 remove
} catch (Exception e) {
Log.d("sendMsg", "--消息发送失败--" + e);
}
}
}
}
首先,msgQueue 唯一的一个 remove()就在此处,程序的其他地方只有 add(),然后这个队列我采取发送第一个,然后删除第一个的方式
然后,程序随机的会报异常 java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.wawa.MySocket.SendMsg.IP' on a null object reference
注意合格异常是随机的,大概 3-5 条消息,就会报一条
我想问下,这个大概是那里错了,我每次发送前都会检查 msgQueue 的 size(),如果为 0 就 continue,而且我反复确认,程序里 msgQueue 只有唯一的一处 remove(),我想问下,这个一般是什么情况
1
guchengyehai1 2020-12-25 20:35:21 +08:00 via Android
Queue 非线程安全容器
|
2
LGA1150 2020-12-25 20:39:02 +08:00 via Android
List 非线程安全
|
3
QBugHunter OP |
4
LGA1150 2020-12-25 20:46:44 +08:00 via Android
@QBugHunter 如果把 ArrayList 换成 Vector 还会出错吗?
|
5
kx5d62Jn1J9MjoXP 2020-12-25 21:00:01 +08:00 via Android
@QBugHunter 两个线程同时 add,会把 msg 加到 arraylist 同一位,两个都对 size 加 1,导致有一位上的 msg 为 null
|
6
Lemeng 2020-12-25 23:54:59 +08:00
非线程
|
7
liufish 2020-12-26 15:20:23 +08:00
子线程直接死循环有点太猛了。
List 换成 BlockingQueue,按生产-消费模式来做试试? |
8
twoyuan 2020-12-26 23:45:43 +08:00
因为 msgQueue.size() 和下面的 msgQueue.get(0) 不是原子化操作,也就是上面说的线程不安全,多线程环境下 size() 后 get() 之前发生了 remove
|