最近在使用启动一个Java进程,然后提供服务:其中程序的启动入口为
log.info("开始启动OI-SOA进程..."); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "springapplicationContext-spring.xml" }); context.start(); log.info("启动OI-SOA进程成功..."); while(true){ System.in.read(); }
使用spring启动服务,然后在while(true)中循环调用System.in.read()阻塞主线程,其中shell脚本的为
startOI.sh:
#!/bin/sh . ~/.bash_profile CLASSPATH=../.:./../lib/* echo ------------------------------------------------------------------- echo ------------------------------------------------------------------- echo ===================start oi service...============================ PROVIDER=com.xxx.oi.main.OiSoaMain MEM_ARGS="-XX:PermSize=256M -XX:MaxPermSize=512M -Xms5120M -Xmx5120M" JAVA_OPTIONS="-Dfile.encoding=GBK" ${JAVA_HOME}/bin/java ${MEM_ARGS} -classpath ${CLASSPATH} ${JAVA_OPTIONS} ${PROVIDER}
start.sh:
#!/bin/sh . ~/.bash_profile #startOI.sh 50888 >/dev/null & ./startOI.sh 50887 >/dev/null &
其中start.sh 可以根据都端口配置启动多个进程
此程序在IBM的AIX上运行正常,最近程序扩容,将服务部署到了RedHat Linux上,启动程序,一个CPU就会被完全的占用,无法释放,导致CPU过高,经过分析,发现是System.in.read();这段代码占用了CPU,增加日志发现是这段代码并没有阻塞,而是一直返回-1,根据Java的API,返回-1表示流已经读取结束(-1
if the end of the stream is reached),但是我并没有往控制台写入数据,程序应该一直阻塞才对。经过测试直接运行${JAVA_HOME}/bin/java ${MEM_ARGS} -classpath ${CLASSPATH} ${JAVA_OPTIONS} ${PROVIDER} 也不会有占用CPU的情况,但是加上 & 让程序作为一个守护进程执行就会有问题,所以怀疑是shell某个地方有问题。
进过各种度娘谷哥,stackoverflow,发现在启动脚本中给程序增加一个指定的终端就能够解决,即:
#!/bin/sh
. ~/.bash_profile
#startOI.sh 20888 >/dev/null &
./startOI.sh 20887 >/dev/null 2>&1 < /dev/tty &
其中/dev/tty就是当前的终端,系统作为守护进程启动,并且指定从当前终端读取数据,如果没有数据就阻塞,如果不加上默认终端,Linux认为没有终端,流已经结束,就直接返回-1了。
PS:阻塞当前线程的的其他方法:
Thread.sleep();
可以将主线程休眠,那么进程就会一直存在不退出。
while(true){ try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException e) { // TODO Auto-generated catch block log.error("oi进程意外结束",e); } }