System.in.read()在Linux无法阻塞的问题

最近在使用启动一个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);
			} 
        }

猜你喜欢

转载自zistrong.iteye.com/blog/2265831
今日推荐