A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© woying123 中级黑马   /  2015-12-7 18:50  /  1127 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  JAVA的内存分配机制,在很多地方都已经解析很多次了,个人如何方便的来直观的了解,还有很多人不是很清楚,或者没有这样的机会,在这里我结合一个小例子,采用JDK自带的JConsole来说一下JVM的内存分配机制。

案例
首先解释下场景,服务端是一个通信服务器,接受客户端发过来的通信信息,并做业务处理;服务端采用JAVA中的MINA2框架,客户端可以任意,C++也好,JAVA也好,只要符合服务端规定的消息结构,发给通信服务器都能处理。

为了让大家更清楚,可以用MINA2框架中的时间服务器的例子来稍作修改模拟这个场景。系统环境,APACHE MINA2.0.4 + JDK1.6 + Eclipse3.7。

服务端代码如下:
Java代码  收藏代码
public class MinaTimeServer {  
    /** We will use a port above 1024 to be able to launch the server with a standard user */  
    private static final int PORT = 9123;  
  
    /**
     * The server implementation. It's based on TCP, and uses a logging filter  
     * plus a text line decoder.
     */  
    public static void main(String[] args) throws IOException {  
        // Create the acceptor  
        IoAcceptor acceptor = new NioSocketAcceptor();  
         
        // Add two filters : a logger and a codec  
        acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );  
        acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));  
        //acceptor.getFilterChain().addLast("exector", new ExecutorFilter(Executors.newCachedThreadPool()));  
        acceptor.getFilterChain().addLast("exector", new ExecutorFilter());  
     
        // Attach the business logic to the server  
        acceptor.setHandler( new TimeServerHandler() );  
         
  
        // Configurate the buffer size and the iddle time  
        acceptor.getSessionConfig().setReadBufferSize( 2048 );  
        acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );  
         
        // And bind !  
        acceptor.bind( new InetSocketAddress(PORT) );  
    }  
}  



业务处理器(这里当作一个时间服务器,接受到信息之后就立刻返回服务器当前时间)
Java代码  收藏代码
public class TimeServerHandler extends IoHandlerAdapter  
{  
    /**
     * Trap exceptions.
     */  
    @Override  
    public void exceptionCaught( IoSession session, Throwable cause ) throws Exception  
    {  
        cause.printStackTrace();  
    }  
  
    /**
     * If the message is 'quit', we exit by closing the session. Otherwise,
     * we return the current date.
     */  
    @Override  
    public void messageReceived( IoSession session, Object message ) throws Exception  
    {  
        String str = message.toString();  
         
        if( str.trim().equalsIgnoreCase("quit") ) {  
            // "Quit" ? let's get out ...  
            session.close(true);  
            return;  
        }  
  
        // Send the current date back to the client  
        Date date = new Date();  
        session.write( date.getTime());  
        System.out.println("Message written...");  
    }  
  
    /**
     * On idle, we just write a message on the console
     */  
    @Override  
    public void sessionIdle( IoSession session, IdleStatus status ) throws Exception  
    {  
        System.out.println( "IDLE " + session.getIdleCount( status ));  
    }  
}  



客户端JAVA代码:
Java代码  收藏代码
import java.net.InetSocketAddress;  
import java.nio.charset.Charset;  
import java.util.ArrayList;  
import java.util.List;  
import java.util.concurrent.CountDownLatch;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Semaphore;  
  
import org.apache.mina.core.future.ConnectFuture;  
import org.apache.mina.filter.codec.ProtocolCodecFilter;  
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;  
import org.apache.mina.filter.logging.LoggingFilter;  
import org.apache.mina.transport.socket.nio.NioSocketConnector;  
  
public class MinaTimeClient {  
      
    public void mutiSendMsg() {  
        // 创建客户端连接器.  
        NioSocketConnector connector = new NioSocketConnector();  
        connector.getFilterChain().addLast("logger", new LoggingFilter());  
        connector.getFilterChain().addLast(  
                "codec",  
                new ProtocolCodecFilter(new TextLineCodecFactory(Charset  
                        .forName("UTF-8")))); // 设置编码过滤器  
        connector.setConnectTimeoutMillis(30000);  
        connector.setHandler(new TimeClientHandler());// 设置事件处理器  
        ConnectFuture cf = connector.connect(new InetSocketAddress("127.0.0.1",  
                9908));// 建立连接  
        cf.awaitUninterruptibly();// 等待连接创建完成  
        cf.getSession().write("hello");// 发送消息  
        cf.getSession().write("quit");// 发送消息  
        cf.getSession().getCloseFuture().awaitUninterruptibly();// 等待连接断开  
        connector.dispose();  
    }  
    public static void main(String[] args) {  
        /*
        MinaTimeClient client = new MinaTimeClient();
        for(int i = 0; i < 1000; i ++) {
            client.mutiSendMsg();
        }*/  
        //int size = keywordMap.size();  
        long startTime = System.currentTimeMillis();  
        int thread_num = 100;  
        int client_num = 2000;  
  
        // TODO Auto-generated method stub  
        ExecutorService exec = Executors.newCachedThreadPool();  
        // 50个线程可以同时访问  
        final Semaphore semp = new Semaphore(thread_num);  
         
        final CountDownLatch countDownLatch = new CountDownLatch(client_num);   
        List<Thread> list = new ArrayList<Thread>();  
        // 模拟2000个客户端访问  
        for (int index = 0; index < client_num; index++) {  
            final int NO = index;  
            Thread run = new Thread() {  
                public void run() {  
                    while(true){      
                        try {  
                             // 获取许可  
                            //semp.acquire();  
                              
                            new MinaTimeClient().mutiSendMsg();  
                             // System.out.println(result);  
                            // Thread.sleep((long) (Math.random()) * 1000);  
                            // 释放  
                            System.out.println("第:" + NO + " 个");  
                           // semp.release();  
                            Thread.sleep(500);  
                        //countDownLatch.countDown();  
                        } catch (InterruptedException e) {  
                            e.printStackTrace();  
                        }  
                          
                    }  
                }  
            };  
            list.add(run);  
            //exec.execute(run);  
        }  
        for (Thread thread : list) {  
            thread.start();  
        }  
         
        //try {  
            //countDownLatch.await();  
            System.out.println("end time::::" + (System.currentTimeMillis() - startTime));  
             // 退出线程池  
          //  exec.shutdown();  
        //} catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
        //  e.printStackTrace();  
        //}   
         
    }  
}  


客户端处理类:
Java代码  收藏代码
public class TimeClientHandler extends IoHandlerAdapter {  
    public TimeClientHandler() {  
    }  
  
    @Override  
    public void messageReceived(IoSession session, Object message)  
            throws Exception {  
        System.out.println(message);// 显示接收到的消息  
    }  
}  

代码准备好之后,启动通信服务器服务端,然后启动客户端;
然后在打开你的jconsole界面,选择需要观察的那个服务端的JAVA进程;
首页就是类似这样的一个界面(注意:这篇文章里面所有的截图都是在模拟程序运行5个小时以后截下来的):

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马