写点什么

Netty- 物联网设备 Channel 管理

用户头像
凸出
关注
发布于: 2020 年 07 月 21 日

物联网设备通过TCP协议接入平台,传输协议使用自定义的二进制协议,形如:

设备与平台链接建立后,设备上报签到报文,平台记录设备 id,建立并记录与 channel 的对应关系。

ConcurrentHashMap

第一反应,我就想到要使用ConcurrentHashMap<String, Channel>来保存 id 与 channel 的对应关系,ConcurrentHashMap的用法很简单,代码如下:

Map<String, AtomicInteger> map = new ConcurrentHashMap<>();map.putIfAbsent("1001", new AtomicInteger());map.get("1001").getAndIncrement();System.out.println(map.get("1001").get());
复制代码

搬到 Channel 管理中:

Map<String, Channel> map = new ConcurrentHashMap<>();
public void put(String id, Channel channel) { Channel prev = map.putIfAbsent("1001", channel); if (prev != null) { //过期的连接 close 或 其他处理 map.remove(id); put(id, channel); }}
复制代码

但,其实这样的用法是错误的,应该直接使用put,代码简化如下:

Map<String, Channel> map = new ConcurrentHashMap<>();
public void put(String id, Channel channel) { Channel prev = map.put("1001", channel); if (prev != null) { //过期的连接 close 或 其他处理 }}
复制代码

可以使用 HashMap 吗?

如果将ConcurrentHashMap修改为HashMap,代码是否会有并发问题?

Map<String, Channel> map = new HashMap<>();
public void put(String id, Channel channel) { Channel prev = map.put("1001", channel); if (prev != null) { //过期的连接 close 或 其他处理 }}
复制代码

一个简单的测试代码:

    Map<String, String> map = new ConcurrentHashMap<>();//    Map<String, String> map = new HashMap<>();
@Test public void test() { Set<String> set = new HashSet<>(); for (int i = 0; i < 10000; i++) { set.add("s" + i); set.add("t" + i); } Thread t = new Thread(()->{ for (int i = 0; i < 10000; i++) { String v = map.put("a", "s" + i); if (v != null) { set.remove(v); } } }); t.start(); for (int i = 0; i < 10000; i++) { String v = map.put("a", "t" + i); if (v != null) { set.remove(v); } } try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(set);
}
复制代码

使用ConcurrentHashMap时,结果如下:

[s9999]
复制代码

使用HashMap时,结果可能如下:

[t327, s4769, t375, t5437, t5435, s3360, s2037, s2090, t4073, t7911, s5939, s100, s5913, t446, t5335, t7992, t7983, s2010, t7962, t7898, t5284, t5267, s4929, s4922, s208, s4961, s4954, t5650, t5656, s1009, s1004, s3649, s3641, t5684, s1032, s2358, t5586, s4804, s326, t5536, s2225, s4883, s4866, s3527, s3585, s2242, t5548, s2168, s2154, t4196, t5802, s419, t779, t5853, s1208, s2534, t5837, s3843, s1258, s1256, t4556, t3213, s2561, s1233, s1288, t3258, s1260, t3160, s501, s3729, t5759, s2433, t3149, s1158, t5788, s1144, s1142, s1084, t4396, t3097, s615, s652, s2784, s1450, s2786, t3427, s1436, s2769, s2762, s2759, t2135, s1485, s1486, t4780, t2118, s1461, t2187, t2179, t2092, t2080, s724, s736, t3310, s1326, s1319, s1371, s1374, s1360, s1367, t2009, t5994, s1343, s1390, s806, s848, t4958, s2978, s2970, s2968, s1619, s1626, t3661, s1685, s1674, s2998, s2995, t1021, s954, t4926, t4925, s2946, s2948, s983, s1616, t3516, s2869, s1539, s2851, s1500, s1574, t3547, s1562, s2880, t3523, s1590, s1596, s1580, s2812, t1207, t1246, s1812, s1804, s1847, s1838, t3757, t3756, t3740, t3723, s1744, t1129, t1120, s1788, t1164, t1151, s1734, s9114, s9178, t1498, s9169, s9156, s9141, s9149, s9198, s9186, t1400, t2716, s9009, s9054, s9041, s9027, s9094, s9072, s9061, s24, s1932, s1924, s1962, s1953, s1940, s8037, s8012, s8091, t2933, t2935, t2911, t2987, t1650, t2981, t2973, t1624, t2951, s9307, s9246, t1545, t2877, t1581, t1530, t1501, s8272, s8263, s9595, s8255, s8202, s9532, s8203, s9556, s8172, t1721, t1710, t1711, t1714, t1779, s9450, t9179, t9175, t9167, s8494, t9148, t9146, t9182, s9726, s9721, s9719, s9710, s9770, s9761, s8437, s8419, s8476, s8472, t9120, s8454, t9108, t9059, s8387, t9037, t9028, t9026, t9022, t9098, t9061, s9613, s9604, s8324, s9655, s8318, s9648, s9637, s8366, s9695, s7038, t9004, t9000, s8345, s9660, t1980, s7006, t8086, s6075, s8642, s8644, s8679, s8654, t8010, s8508, s8554, s8546, s8544, s8596, s8571, t9225, s8925, s8907, s8901, s8838, s8829, s8881, s6227, t9517, s6208, s8865, t9501, s8857, s6260, t9565, t9544, s8899, t8280, t8263, t8258, t8181, t8178, t8170, s8801, s8767, s8750, s8759, s8780, s6128, t8154, t9484, t9483, t8149, s7754, s7723, s6461, t8445, t7110, s5115, t7148, t7145, s6498, t8466, t7134, s6472, t7194, t7161, s6309, s6305, s7619, s8933, s7674, t8321, t9643, s6336, t8309, t8306, s8985, s8979, s6373, t8354, t9662, t7065, t8381, t8383, t8374, t8713, s6735, t8707, s6653, s6637, t8670, t9999, t8658, t6053, s4063, t6041, t8696, t6083, t6089, s7872, t8511, t8506, s7841, t7234, t7225, s6576, t8547, t8540, t8542, s7882, t7205, s5296, s5297, t8585, s6596, t7290, t7284, t8922, t8917, s6936, t8907, t8901, s6910, s6981, t8969, t8964, t8960, s4328, s5658, s5657, s4321, s6976, t8943, s6968, s5635, t7559, t7554, s4247, t8874, t6215, t8870, t6209, t8867, t8864, t7523, t6262, t6251, t6244, t6239, t7562, s5586, t6286, t6275, s6802, t8844, t8841, s6869, t8839, s5527, s5529, s5515, s6787, t8758, s6775, s6761, t8741, s6767, s6769, t6149, t8799, t6184, s4175, t7487, t6153, t6192, t7836, t6501, s5831, t7803, t6542, t7867, t6536, s3224, s4551, t6526, s5871, s5868, s5865, s3201, t5122, t5119, s5781, t5102, s5783, t5176, t6494, t6486, t5148, s3167, t5192, s5729, s5720, s5718, s3111, t7740, s5765, t6400, t7730, s3030, t6347, s3036, t6332, t8994, s4357, s3022, s4354, s3019, s4349, s5679, t6319, t8977, s5667, s6997, s3001, s6993, t6389, t6379, s3067, s3051, s3053, s3042, t5076, s3099, s3081, t5068, t6394]
复制代码

即:

HashMap在并发put时,value 会被其他线程覆盖。要使用ConcurrentHashMap来保证 put 线程安全。

发布于: 2020 年 07 月 21 日阅读数: 80
用户头像

凸出

关注

技术凸出->架构凸出->业务凸出->腰椎凸出 2017.10.20 加入

还未添加个人简介

评论

发布
暂无评论
Netty-物联网设备Channel管理