mina线程总结

来源:互联网 发布:兴奋剂 知乎 编辑:程序博客网 时间:2024/06/18 08:52

今天对mina的线程做了些实验,先上代码

MyCodecFactory:

public class MyCodecFactory implements ProtocolCodecFactory{    ProtocolEncoderAdapter encoder = new MyEncoder();    ProtocolDecoder decoder = new MyDecoder();    public ProtocolDecoder getDecoder(IoSession session) throws Exception    {        return decoder;    }    public ProtocolEncoder getEncoder(IoSession session) throws Exception    {        return encoder;    }}

MyDecoder:

public class MyDecoder extends ProtocolDecoderAdapter{    @Override    public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception    {        int   id  = in.getInt();          int   len = in.getInt();          byte []  dst =  new   byte [len];                    in.get(dst);                    String name = new  String(dst,"GBK");                    Item item = new  Item();          item.setId(id);          item.setName(name);          out.write(item);       }    }

MyEncoder:

public class MyEncoder extends ProtocolEncoderAdapter{    public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception    {        Item item = (Item) message;        int byteLen = 8 + item.getName().getBytes("GBK").length;        IoBuffer buf = IoBuffer.allocate(byteLen);        buf.putInt(item.getId());        buf.putInt(item.getName().getBytes("GBK").length);        buf.put(item.getName().getBytes("GBK"));        buf.flip();        out.write(buf);    }}
ClientSessionHandle:

public class ClientSessionHandle implements IoHandler{    @Override    public void sessionCreated(IoSession session) throws Exception    {        System.out.println("client sessionCreated" + System.currentTimeMillis());    }    @Override    public void sessionOpened(IoSession session) throws Exception    {        System.out.println("client sessionOpened" + System.currentTimeMillis());    }    @Override    public void sessionClosed(IoSession session) throws Exception    {        System.out.println("client sessionClosed" + System.currentTimeMillis());    }    @Override    public void sessionIdle(IoSession session, IdleStatus status) throws Exception    {        System.out.println("client sessionIdle" + System.currentTimeMillis());    }    @Override    public void exceptionCaught(IoSession session, Throwable cause) throws Exception    {        cause.printStackTrace();        System.out.println("client exceptionCaught" + System.currentTimeMillis());    }    @Override    public void messageReceived(IoSession session, Object message) throws Exception    {        System.out.println("recieveMsg:" + System.currentTimeMillis());    }    @Override    public void messageSent(IoSession session, Object message) throws Exception    {//      Thread.sleep(3000);        System.out.println("client messageSent" + System.currentTimeMillis());    }}
ServerSessionHandle:

public class ServerSessionHandle implements IoHandler{    @Override    public void sessionCreated(IoSession session) throws Exception    {        System.out.println("server sessionCreated" + System.currentTimeMillis());    }    @Override    public void sessionOpened(IoSession session) throws Exception    {        System.out.println("server sessionOpened" + System.currentTimeMillis());    }    @Override    public void sessionClosed(IoSession session) throws Exception    {        System.out.println("server sessionClosed" + System.currentTimeMillis());    }    @Override    public void sessionIdle(IoSession session, IdleStatus status) throws Exception    {        System.out.println("server sessionIdle" + System.currentTimeMillis());    }    @Override    public void exceptionCaught(IoSession session, Throwable cause) throws Exception    {        cause.printStackTrace();        System.out.println("server exceptionCaught");    }    @Override    public void messageReceived(IoSession session, Object message) throws Exception    {//        Thread.sleep(3000);        System.out.println("server recieveMsg:" + System.currentTimeMillis());    }    @Override    public void messageSent(IoSession session, Object message) throws Exception    {        System.out.println("server messageSent" + System.currentTimeMillis());    }}
Client:

public class Client{    public static void main(String[] args) throws IOException    {        IoConnector connector = new NioSocketConnector();        connector.getFilterChain().addLast("protocol", new ProtocolCodecFilter(new MyCodecFactory()));        connector.setHandler(new ClientSessionHandle());//        connector.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));        ConnectFuture future = connector.connect(new InetSocketAddress(8888));        future.awaitUninterruptibly();        IoSession session = future.getSession();        Item item = new Item();        item.setId(1);        item.setName("aaa");        session.write(item);        session.write(item);        session.write(item);        session.write(item);        session.write(item);    }}
Server:

public class Server{    public static void main(String[] args) throws IOException    {        IoAcceptor acceptor = new NioSocketAcceptor();        acceptor.getFilterChain().addLast("protocol", new ProtocolCodecFilter(new MyCodecFactory()));//        acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));         acceptor.setHandler(new ServerSessionHandle());        acceptor.bind(new InetSocketAddress(8888));    }}

mina简介

mina的工作模式如下图所示

acceptor用于处理客户端的连接,当有客户端连接时,将连接交给Processor处理,Process是多线程的,在内部由一个线程池来处理,线程的个数由创建Acceptor时参数指定,默认是cpu核数加1,filter主要用来对消息进行过虑,经常用来做编码解码,消息经过filter过虑之后由handler来处理,我们做开发时业务也都是在handler层做。

一个客户端连接到服务器端之后,由一个且只会有一个processor来处理。服务器启动后,processor的数量是0,每一个客户端连接上来,就会创建一个Processor,直到达到最高数量。当所有的processor都在处理客户端的信息时,后续的客户端都会产生阻塞,所以当同时处理消息量过多,io不多,但是handler处理时间较长时,我们就要采用另一种处理方式 ,即把handler放在另外的线程来处理,代码如下:

acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));

实验过程

这篇文章的重点内容是来实验mina的线程问题,主要是processor和handler使用不同线程处理客户端消息的情况,实验内容是客户端连接成功之后连续发送5条消息

(1)客户端与服务器端都不采用handler单独线程,客户端ClientSessionHandle的messageSent方法延迟3s发送,结果如下,消息是排着队发送

           客户端结果

client sessionCreated1384482297824
client sessionOpened1384482297825
client messageSent1384482300829
client messageSent1384482303829
client messageSent1384482306830
client messageSent1384482309830
client messageSent1384482312830

           服务器结果

server sessionCreated1384482297813
server sessionOpened1384482297813
server recieveMsg:1384482297828
server recieveMsg:1384482300829
server recieveMsg:1384482303830
server recieveMsg:1384482306830
server recieveMsg:1384482309830

(2)客户端采用handler单独线程,客户端ClientSessionHandle的messageSent方法延迟3s发送,结果如下,消息是连接成功之后延迟3s并行发送出去

           客户端结果

client sessionCreated1384482710537
client sessionOpened1384482710538
client messageSent1384482713542
client messageSent1384482713542
client messageSent1384482713542
client messageSent1384482713542
client messageSent1384482713542

           服务器结果

server sessionCreated1384482710525
server sessionOpened1384482710526
server recieveMsg:1384482710541
server recieveMsg:1384482710541
server recieveMsg:1384482710542
server recieveMsg:1384482710542
server recieveMsg:1384482710542

(3)客户端采用handler单独线程,客户端连接成功之后不延迟3s直接发送5条消息,服务器端ServerSessionHandle延迟3s接收,结果如下,5条消息是一起发出,但服务器端每3s处理一条消息,jconcle监控发现只有一个processor线程,由此验证了:一个客户端只会有一个processor进行处理,handler与processor同一线程的情况下,消息是排队的。

           客户端结果

client sessionCreated1384482908375
client sessionOpened1384482908377
client messageSent1384482908380
client messageSent1384482908380
client messageSent1384482908381
client messageSent1384482908381
client messageSent1384482908381

           服务器结果

server sessionCreated1384482908372
server sessionOpened1384482908372
server recieveMsg:1384482911381
server recieveMsg:1384482914382
server recieveMsg:1384482917382
server recieveMsg:1384482920382
server recieveMsg:1384482923382

(4)客户端与服务器端都采用handler单独线程,客户端连接成功之后不延迟3s直接发送5条消息,服务器端ServerSessionHandle延迟3s接收,结果如下,5条消息是一起发出,服务端延迟3s后一起处理了5条消息,jconcle监控发现还是只有一个processor线程,但还会创建另外5个线程,这五个线程各自处理了一条消息,由此验证了:一个客户端只会有一个processor进行处理,processor接收到客户端的消息之后,放到了handler处理线程中处理。

           客户端结果

client sessionCreated1384483318084
client sessionOpened1384483318086
client messageSent1384483318088
client messageSent1384483318089
client messageSent1384483318089
client messageSent1384483318089
client messageSent1384483318089

           服务器结果

server sessionCreated1384483318081
server sessionOpened1384483318082
server recieveMsg:1384483321090
server recieveMsg:1384483321091
server recieveMsg:1384483321091
server recieveMsg:1384483321091
server recieveMsg:1384483321091




原创粉丝点击