mina线程总结

今天对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




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值