public class ServerMessageDecoder extends CumulativeProtocolDecoder { private final Charset charset = Charset.forName("UTF-8"); private IoBuffer buff = IoBuffer.allocate(320).setAutoExpand(true); //private static int count = 0; @Override public boolean doDecode(IoSession iosession, IoBuffer iobuffer, ProtocolDecoderOutput out) throws Exception { ...; } 想问下,这个doDecode方法是不是线程安全的? 从我打印的log来看好像不是线程安全的… 也就是说会有多个线程调用doDeocde. |
|
95分 |
——-从我打印的log来看好像不是线程安全的… 也就是说会有多个线程调用doDeocde.
这句话说错了,有多个线程调用并不代表就是非线程安全。是否线程安全是根据多个线程和单个线程调用的结果是否一致确定的。 |
嗯,对的,我说错了 如果一次没有读完,假设这个ioseesion是A,如何保证下次来的数据是A的呢,其它线程也会写数据的..是不是自己要写同步方法维护? |
|
是的,要自己写同步方法实现数据的一致性。
|
|
5分 |
从语义上看ServerMessageDecoder?这种底层的类属于功能类,本身就不应该有状态,简单的说,不应该有自己的成员变量之类的东西,所以在多线程的环境下是没有问题的。如果你把状态之类的东西放在这个类里,就理所应当没办法保证安全了
|
private final Charset charset = Charset.forName("UTF-8"); //private IoBuffer buff = IoBuffer.allocate(320).setAutoExpand(true); private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context"); private Context getContext(IoSession session) { Context context = (Context) session.getAttribute(CONTEXT); if (null == context) { context = new Context(); session.setAttribute(CONTEXT, context); } return context; } @Override public boolean doDecode(IoSession iosession, IoBuffer iobuffer, ProtocolDecoderOutput out) throws Exception { boolean complete = false; Context ctx = this.getContext(iosession); ctx.append(iobuffer); IoBuffer buf = ctx.getBuffer(); buf.flip(); while (buf.hasRemaining()) { byte b = buf.get(); /** * CIMConstant.MESSAGE_SEPARATE 为消息界限 * 当一次收到多个消息时,以此分隔解析多个消息 */ if (b == CIMConstant.MESSAGE_SEPARATE ) { complete = true; break; } /*else { buff.put(b); }*/ } if (complete) { buf.flip(); byte[] bytes = new byte[buf.limit()-1]; buf.get(bytes); String message = new String(bytes, charset); buf.clear(); ctx.reset(); System.out.println("iosessionid = " + iosession.getId() +" &&&&&&&&&&&&& = " +message); SentBody body = new SentBody(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new ByteArrayInputStream(message.getBytes(charset))); body.setKey(doc.getElementsByTagName("key").item(0).getTextContent()); NodeList items = doc.getElementsByTagName("data").item(0).getChildNodes(); for (int i = 0; i < items.getLength(); i++) { Node node = items.item(i); body.getData().put(node.getNodeName(), node.getTextContent()); } out.write(body); } return complete; } private class Context { private final IoBuffer innerBuffer; public Context() { innerBuffer = IoBuffer.allocate(320).setAutoExpand(true); } public void reset() { this.innerBuffer.clear(); } public void append(IoBuffer in) { innerBuffer.put(in); } public IoBuffer getBuffer() { return this.innerBuffer; } } |