今天做一个mysql数据恢复的小程序,采用Runtime.exec的方式来执行mysql命令。主要用来恢复一些由定时程序自动备份出来的数据库文件,有时候可能会出现恢复的数据在数据库中还存在,于是会出现主键重复的错误,于是我在恢复的时候加入–force参数,手动在cmd控制台下执行可以很明显看到mysql返回了一些duplicate的error,按道理在java app中也能正常执行过去,可在执行java app的时候看控制台中打印的日志显示,程序阻塞在了waitFor这一步。我的程序片段如下:
……
p = Runtime.getRuntime().exec(cmd);
……
p.waitFor();
……
百思不得其解,最后在google了下,找到一片最早分析该原因的文章是在javaworld上。原因是操作系统这一层对输入输出流有一个buffer,由于受到这个buffer的大小限制,当buffer满了而又没有线程去读,则当前执行的线程就会阻塞掉,于是修改一下程序,开辟两个线程专门用于读取输出流,一个用于读取返回消息流,一个用于读取异常消息流,于是修改程序如下:
……
p = Runtime.getRuntime().exec(cmd);
new PrintStream(p.getInputStream()).start();
new PrintStream(p.getErrorStream()).start();
p.waitFor();
……
此处PrintStream为一个读取inputstream的线程。
Leave a Reply