现在的位置: 首页 > 综合 > 正文

Swing 程序 多次打开 运行在同一java虚拟机 的实现

2018年04月16日 ⁄ 综合 ⁄ 共 10306字 ⁄ 字号 评论关闭

问题描述:

用java swing写了个记事本程序,并打成了exe文件在windows下运行,但是每次启动,都会启动一个java虚拟机,每个java虚拟机的启动,都会大量消耗内存。特别是将系统txt文件的默认打开方式设置为本记事本程序时,每双击打开一个记事本,就启动一个jvm,内存消耗30于M,更重要的是,启动jvm很耗时间,在自己的机器上(i5处理器)启动该记事本程序需要2—5秒的时间,用着很不爽。

 

解决办法:

第一次启动程序时,同时启动一个监听,当以后再次启动记事本程序时,首先与监听器进行通信,并将用户操作信息发送给监听器,用户的操作由监听器所属的java虚拟机完成,如此则保证了所有记事本的相关操作在同一个jvm中进行。

 

代码:

Java代码
复制代码
 收藏代码
  1. public static void main(String args[]) {
      
  2.   
  3.         final String[] filePathArray = args;   
  4.            
  5.         //设定端口、IP  
  6.         final String ip = "127.0.0.1";   
  7.         final int port = 12530;
      
  8.   
  9.         ObjectOutputStream out = null;   
  10.         Socket socket = null;   
  11.         try {   
  12.             //检测记事本程序是否已启动,如果已启动,则由已启动的记事本程序来新建或打开文档,如果未启动,则启动记事本程序,并启动监听。  
  13.             //连接本机指定端口,如果连接失败(表现形式,抛Connect异常),则说明记事本程序尚未启动。  
  14.             socket = new Socket(ip,port);   
  15.             out = new ObjectOutputStream(socket.getOutputStream());   
  16.               
  17.             //根据路径打开指定文档  
  18.             if(filePathArray != null && filePathArray.length > 0){
      
  19.                 out.writeObject(filePathArray);   
  20.                
  21.             //新建空白文档  
  22.             }else{   
  23.                 out.writeObject("new");   
  24.             }   
  25.             SplashScreen ss = SplashScreen.getSplashScreen();   
  26.             if (ss != null) {   
  27.                 ss.close();   
  28.             }   
  29.             //退出java虚拟机  
  30.             System.exit(0);   
  31.            
  32.         } catch (Exception e) {   
  33.             //-----------抛异常说明记事本程序尚未启动-------------  
  34.             //1、================初始化日志=================  
  35.             log = Logger.getLogger(Index.class);   
  36.                
  37.             // 2、================验证应用程序同级目录下,log文件夹是否存在,如果不存在,则创建。================  
  38.             File file_log = new File("log");   
  39.             if (!file_log.exists() || !file_log.isDirectory()) {   
  40.                 if (!file_log.mkdirs()) {   
  41.                     JOptionPane.showMessageDialog(null"创建log目录失败!");   
  42.                     System.exit(0);   
  43.                 }   
  44.             }   
  45.             // 3、================验证应用程序同级目录下,config文件夹是否存在,如果不存在,则创建。================  
  46.             File file_config = new File("config");   
  47.             if (!file_config.exists() || !file_config.isDirectory()) {   
  48.                 if (!file_config.mkdirs()) {   
  49.                     JOptionPane.showMessageDialog(null"创建config目录失败!");   
  50.                     System.exit(0);   
  51.                 }   
  52.             }   
  53.             //4、================新启线程,监听socket连接================  
  54.             new Thread(){   
  55.                 @Override  
  56.                 public void run() {   
  57.                     ObjectInputStream serverIn = null;   
  58.                     Socket clientSocket = null;   
  59.                     try {   
  60.                         ServerSocket serverSocket = new ServerSocket(port);   
  61.                         while(true){   
  62.                             //accept()会阻塞当前线程的继续执行,当有新客户端接入,才会向下运行。  
  63.                             clientSocket = serverSocket.accept();   
  64.                             serverIn = new ObjectInputStream(clientSocket.getInputStream());   
  65.                                
  66.                             //取得客户端发送的数据  
  67.                             final Object getMsg = serverIn.readObject();   
  68.                                 
  69.                             //每个记事本启动时,只会向服务器端发一条信息(new 或 要打开文档的地址),所以处理完请求则关闭相应资源。  
  70.                             try {   
  71.                                  serverIn.close();   
  72.                             } catch (IOException e) {   
  73.                                 log.error(null, e);   
  74.                             }   
  75.                             try {   
  76.                                 clientSocket.close();   
  77.                             } catch (Exception e) {   
  78.                                 log.error(null, e);   
  79.                             }   
  80.                                
  81.                             //如果客户端发送的信息是 new ,则新建空白文档  
  82.                             if(getMsg.toString().equals("new")){   
  83.                                 SwingUtilities.invokeLater(new Runnable(){   
  84.                                     @Override  
  85.                                     public void run() {   
  86.                                         MyNotePad note = new MyNotePad(nullnullnull);
      
  87.                                         note.setVisible(true);   
  88.                                     }   
  89.                                 });   
  90.                             }else{   
  91.                                 //否则,根据客户端发送过来的路径,打开指定文档。  
  92.                                 SwingUtilities.invokeLater(new Runnable(){   
  93.                                     @Override  
  94.                                     public void run() {   
  95.                                         String[] files = (String[])getMsg;   
  96.                                         for(int i=0;i<files.length;i++){
      
  97.                                             MyNotePad note = new MyNotePad(nullnull,files[i]);
      
  98.                                             note.setVisible(true);   
  99.                                         }   
  100.                                     }   
  101.                                 });   
  102.                             }   
  103.                         }   
  104.                     } catch (Exception e2) {   
  105.                         log.error(null, e2);   
  106.                     }   
  107.                 }   
  108.             }.start();   
  109.         }   
  110.   
  111.         //5、================启动记事本程序================  
  112.         // 设置系统字体  
  113.         SysFontAndFace.setSysFontAndFace();   
  114.   
  115.         // 设置输入中文时,不显示输入框  
  116.         System.setProperty("java.awt.im.style""on-the-spot");   
  117.   
  118.         try {   
  119.             //打开指定路径的文档  
  120.             if (filePathArray != null && filePathArray.length > 0) {
      
  121.                 SwingUtilities.invokeAndWait(new Runnable(){   
  122.                     @Override  
  123.                     public void run() {   
  124.                         for (int i = 0; i < filePathArray.length; i++) {
      
  125.                             MyNotePad note = new MyNotePad(nullnull,filePathArray[i]);
      
  126.                             note.setVisible(true);   
  127.                         }   
  128.                     }   
  129.                 });   
  130.             // 打开空白文档  
  131.             } else {   
  132.                 SwingUtilities.invokeAndWait(new Runnable(){   
  133.                     @Override  
  134.                     public void run() {   
  135.                         MyNotePad note = new MyNotePad(nullnullnull);
      
  136.                         note.setVisible(true);   
  137.                     }   
  138.                 });   
  139.             }   
  140.         } catch (Exception e) {   
  141.             JOptionPane.showMessageDialog(null"出错了,请重新启动!");   
  142.             System.exit(1);   
  143.         }   
  144.            
  145.         //6、================启动定时任务,负责执行gc================  
  146.         //创建定时器,一分钟后开始执行,以后每分钟执行一次。  
  147.         Timer timer = new Timer();   
  148.         timer.schedule(new TimerTask(){   
  149.             @Override  
  150.             public void run() {   
  151.                 System.gc() ;   
  152.             }   
  153.                
  154.         }, 60*1000,60*1000);
      
  155.   
  156.         // 7、================关闭欢迎信息================  
  157.         SplashScreen ss = SplashScreen.getSplashScreen();   
  158.         if (ss != null) {   
  159.             ss.close();   
  160.         }   
  161.        
  162.     }  

 

 效果:

经前后对比试验,数据如下:

双击启动时间:改造前(2--5秒),改造后(几乎无延迟,1秒内)

同时打开多个文档:改造前(打开一次30M,打开几次则几个30M),改造后(打开一次与打开多次差距不大,始终维持在40M左右)

 

不足:

监听程序会常驻内存,关闭记事本程序不会释放(这也正是启动迅速的原因),不过现在的机器配置都很高,30M的内存可以忽略。

 

抱歉!评论已关闭.