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

2 篇文章 0 订阅

问题描述:

用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.     }  
public static void main(String args[]) {

		final String[] filePathArray = args;
		
		//设定端口、IP
		final String ip = "127.0.0.1";
		final int port = 12530;

		ObjectOutputStream out = null;
		Socket socket = null;
		try {
			//检测记事本程序是否已启动,如果已启动,则由已启动的记事本程序来新建或打开文档,如果未启动,则启动记事本程序,并启动监听。
			//连接本机指定端口,如果连接失败(表现形式,抛Connect异常),则说明记事本程序尚未启动。
			socket = new Socket(ip,port);
			out = new ObjectOutputStream(socket.getOutputStream());
           
			//根据路径打开指定文档
        	if(filePathArray != null && filePathArray.length > 0){
        		out.writeObject(filePathArray);
        	
        	//新建空白文档
        	}else{
        		out.writeObject("new");
        	}
        	SplashScreen ss = SplashScreen.getSplashScreen();
    		if (ss != null) {
    			ss.close();
    		}
        	//退出java虚拟机
        	System.exit(0);
        
		} catch (Exception e) {
			//-----------抛异常说明记事本程序尚未启动-------------
			//1、================初始化日志=================
			log = Logger.getLogger(Index.class);
			
			// 2、================验证应用程序同级目录下,log文件夹是否存在,如果不存在,则创建。================
			File file_log = new File("log");
			if (!file_log.exists() || !file_log.isDirectory()) {
				if (!file_log.mkdirs()) {
					JOptionPane.showMessageDialog(null, "创建log目录失败!");
					System.exit(0);
				}
			}
			// 3、================验证应用程序同级目录下,config文件夹是否存在,如果不存在,则创建。================
			File file_config = new File("config");
			if (!file_config.exists() || !file_config.isDirectory()) {
				if (!file_config.mkdirs()) {
					JOptionPane.showMessageDialog(null, "创建config目录失败!");
					System.exit(0);
				}
			}
        	//4、================新启线程,监听socket连接================
			new Thread(){
				@Override
				public void run() {
					ObjectInputStream serverIn = null;
					Socket clientSocket = null;
					try {
						ServerSocket serverSocket = new ServerSocket(port);
						while(true){
							//accept()会阻塞当前线程的继续执行,当有新客户端接入,才会向下运行。
							clientSocket = serverSocket.accept();
							serverIn = new ObjectInputStream(clientSocket.getInputStream());
							
							//取得客户端发送的数据
		            		final Object getMsg = serverIn.readObject();
		            		 
		            		//每个记事本启动时,只会向服务器端发一条信息(new 或 要打开文档的地址),所以处理完请求则关闭相应资源。
			                try {
								 serverIn.close();
							} catch (IOException e) {
								log.error(null, e);
							}
							try {
								clientSocket.close();
							} catch (Exception e) {
								log.error(null, e);
							}
		            		
		            		//如果客户端发送的信息是 new ,则新建空白文档
			                if(getMsg.toString().equals("new")){
			                	SwingUtilities.invokeLater(new Runnable(){
									@Override
									public void run() {
										MyNotePad note = new MyNotePad(null, null, null);
										note.setVisible(true);
									}
			                	});
			                }else{
			                	//否则,根据客户端发送过来的路径,打开指定文档。
			                	SwingUtilities.invokeLater(new Runnable(){
									@Override
									public void run() {
										String[] files = (String[])getMsg;
					                	for(int i=0;i<files.length;i++){
					                		MyNotePad note = new MyNotePad(null, null,files[i]);
					                		note.setVisible(true);
					                	}
									}
			                	});
			                }
						}
					} catch (Exception e2) {
						log.error(null, e2);
					}
				}
			}.start();
		}

		//5、================启动记事本程序================
		// 设置系统字体
		SysFontAndFace.setSysFontAndFace();

		// 设置输入中文时,不显示输入框
		System.setProperty("java.awt.im.style", "on-the-spot");

		try {
			//打开指定路径的文档
			if (filePathArray != null && filePathArray.length > 0) {
				SwingUtilities.invokeAndWait(new Runnable(){
					@Override
					public void run() {
						for (int i = 0; i < filePathArray.length; i++) {
							MyNotePad note = new MyNotePad(null, null,filePathArray[i]);
							note.setVisible(true);
						}
					}
	        	});
			// 打开空白文档
			} else {
				SwingUtilities.invokeAndWait(new Runnable(){
					@Override
					public void run() {
						MyNotePad note = new MyNotePad(null, null, null);
						note.setVisible(true);
					}
	        	});
			}
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, "出错了,请重新启动!");
			System.exit(1);
		}
		
		//6、================启动定时任务,负责执行gc================
		//创建定时器,一分钟后开始执行,以后每分钟执行一次。
		Timer timer = new Timer();
		timer.schedule(new TimerTask(){
			@Override
			public void run() {
				System.gc() ;
			}
			
		}, 60*1000,60*1000);

		// 7、================关闭欢迎信息================
		SplashScreen ss = SplashScreen.getSplashScreen();
		if (ss != null) {
			ss.close();
		}
	
	}

 

 效果:

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

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

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

 

不足:

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值