美文网首页
java使用Runtime.getRuntime().exec(

java使用Runtime.getRuntime().exec(

作者: 幻想的绝望 | 来源:发表于2019-11-01 11:01 被阅读0次

    最近需要用java程序做一个linux命令定时执行工具,看来看去java能运行外部linux命令的就只有Runtime.getRuntime().exec()了,只是《深入理解java虚拟机》中138也提道此命令运行过程如下

    首先克隆一个和当前虚拟机拥有一样的环境变量的进程,再利用这个新的进程去执行外部命令,最后再推出这个进程,如果频繁执行这个操作,系统消耗会很大,不仅是cpu,内存负担也很重

    下面是我自己写的springboot程序做的性能测试

        @Bean
        public ThreadPoolExecutor threadPoolTaskScheduler() {
            return new ThreadPoolExecutor(50, 50, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1000));
        }
    

    LinuxApplication启动类加入一个线程池bean,创建了一个核心线程数为50的线程池,用来执行线程

        @Scheduled(cron = "0 * * * * ?")
        public void pingStart() {
            try {
                for (int i = 0; i < 100; i++) {
                    threadPoolExecutor.execute(new Runnable() {
                        @Override
                        public void run() {
                            //String[] command = {"ping 192.168.150.144"};//windows测试命令
                            String[] command = {"ping -c 5 -i 0.5 192.168.150.144"};//linux测试命令
                            String result = LinuxExecuteUtils.execute(command);//内部封装Runtime.getRuntime().exec()
                            log.info(result);
                        }
                    });
                }
            } catch (Exception e) {
                log.error("主机拨测异常", e);
            }
        }
    

    定时任务为一分钟一次,每次往线程池加入100个线程,每个线程执行一样的ping命令,我自己把Runtime.getRuntime().exec()封装在了LinuxExecuteUtils里面,具体代码就不贴了。

    首先在windows上测试,程序运行前进程数为77


    程序运行前

    程序运行后cpu使用率直接爆满,进程数到达132,的确是启动了一个新的进程(ping.exe),且5秒后立即恢复到未启动时的水平。


    50核心线程池程序运行后
    进程页面查看ping.exe

    根据cpu波动,只有在前几秒cpu使用率才到达了99%,也就是说上的测试内容大概可以概括为启动50个线程在5秒内立即执行完100个ping命令,那么换一个测试思路,启动5个线程,在50秒内缓慢执行完100个ping命令,看看windows的cpu使用率。

    修改线程池

        @Bean
        public ThreadPoolExecutor threadPoolTaskScheduler() {
            return new ThreadPoolExecutor(5, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1000));
        }
    

    启动程序后进程数和cpu使用率都上浮一截,且之后一直维持这个水平。


    5核心线程池程序启动后

    接下来就是程序部署linux测试, 下面是线程池核心数为50(启动50个线程在5秒内立即执行完100个ping命令)CPU使用率和内存使用率截图


    程序启动PID 50核心线程池运行中

    程序启动的进程号的确是2812,我也确实检查了日志文件,的确是瞬时输出50条ping命令的结果,可是观测才来cpu使用率最大只到达了1.3%,和windows差异巨大,看上去好像Runtime.getRuntime().exec()在linux上并不太消耗性能(还需仔细研究,待定)。

    接下来科普一下windows和linux之间的区别

    windows:进程和线程的概念明确,进程对应于运行实例,线程则是程序代码执行的最小单元
    linux:只有进程而没有线程,利用fork()和exec函数族来操作多线程

    那么仅仅因为linux只有进程就能的出结论Runtime.getRuntime().exec()在linux上并不太消耗性能吗?我上文也只是说了好像,程序测试也不是很完美,进程创建总的来说是一件很耗资源的事,能不用就尽量不用,能少用就尽量少用。

    最后对于真的要使用Runtime.getRuntime().exec()的可以去http://commons.apache.org/proper/commons-exec/index.html看看,开源社区做了jar包封装了这个命令,做了优化。

    想我所见,思我说闻
    写我所想,写我所思
    不求处处皆对 
    只求问心无愧
    

    相关文章

      网友评论

          本文标题:java使用Runtime.getRuntime().exec(

          本文链接:https://www.haomeiwen.com/subject/wzzxbctx.html