关于Process和Thread的问题

问题描述

功能描述,开启多个线程,每个线程都通过Process来调用cmd对网络进行ping,当线程执行完成后回显结果,现在的问题是,只有等全部线程中的process调用的cmd命令完成后才能进行输出,给我的感觉是当一个线程内的Process执行时,其他的线程是挂起状态。为说明这一点,我特意做了下修改,如果是ping百度的话,我要求ping5次,ping谷歌只ping1次,预想的结果是谷歌的结果很快就先显示出来,然后过一下再显示百度的结果(百度ping5次,一般需要5秒钟的时间),但现在的效果是谷歌不显示,等到百度也ping完成后同时显示,顺序不定,这时候体现出了线程抢资源的效果。我还在api上查了一下process的资料,里面有这样一句话:“对于带有 Process 对象的 Java 进程,没有必要异步或并发执行由 Process 对象表示的进程。”难道有Process的对象不能进行多线程异步操作?代码如下:Ping类package ping;import java.io.BufferedReader;import java.io.InputStreamReader;public class Ping implements Runnable {private String name;private String ip;Ping() {}Ping(String name, String ip) {this.name = name;this.ip = ip;}public String getName() {return name;}public String getIp() {return ip;}public void run() {System.out.println(this.name + "start");StringBuffer buf = new StringBuffer();String s = "";Process process;try {if (this.name.compareTo("百度") == 0) {process = Runtime.getRuntime().exec("cmd /c ping " + this.ip + " -n 5");} else {process = Runtime.getRuntime().exec("cmd /c ping " + this.ip + " -n 1");}BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));buf.append(this.name);while ((s = br.readLine()) != null) {buf.append(s + "n");}// process.waitFor();int index0 = buf.indexOf("(") + 1;int index1 = buf.indexOf("%");process.destroy();System.out.println(this.name + "t" + buf.substring(index0, index1));} catch (Exception ex) {ex.printStackTrace();}}}测试类:package ping;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.List;public class Test {public static void main(String args[]) {String driver = "com.mysql.jdbc.Driver";String url = "jdbc:mysql://127.0.0.1:3306/ping";String user = "root";String password = "123";List<Ping> list = new ArrayList<Ping>();try {Class.forName(driver);Connection conn = DriverManager.getConnection(url, user, password);Statement statement = conn.createStatement();String sql = "SELECT * FROM hostlist";ResultSet rs = statement.executeQuery(sql);while (rs.next()) {String name = rs.getString("name");String ip = rs.getString("ip");Ping p = new Ping(name, ip);list.add(p);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}for (int i = 0; i < list.size(); i++) {Ping p = list.get(i);new Thread(p, p.getName()).start();}}}

解决方案

问题出在下面的代码:BufferedReader br = new BufferedReader(new InputStreamReader( process.getInputStream())); buf.append(this.name); while ((s = br.readLine()) != null) { buf.append(s + "n"); } 确切的说是在readline方法中,readLine方法是存在缓冲区的,这种缓冲区会造成阻塞,这个在Process的Javadoc中也有说明:Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.如果不适用readLine,应该就没有这个问题了。BTW,InputStreamReader实例化的时候最好指定编码方式,默认编码方式可能会所在native platform的编码方式不一致

时间: 2024-10-24 19:47:44

关于Process和Thread的问题的相关文章

Activity, Service,Task, Process and Thread之间的关系

Activity, Service,Task, Process and Thread之间到底是什么关系呢? 首先我们来看下Task的定义,Google是这样定义Task的:a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack. A task is a stack of activities, not a class

Process Thread Window之关系

许多人包括我自己,对於window与process或Thread间的对应,常感困扰,我就目前所知者,大概的介绍一下:一个Process有自己4GB的位址空间,这个观念比较容易接受,但是它却不是执行程式的单位,真正执行程式者是Thread,每个Process被Create时,便会有一个主thread 来执行它,我们又可以Create其他的Thread来执行程式,假设现在就有两个thread於这个Process了,那麽,这两个Thread原则上是共用Process的同一个位址空间,例如:背景列印,但

【整理】MySQL 复制的工作方式

      写这篇文章的原因是,看到开源中国上的一篇投稿翻译文章,其中很多地方被翻译的错误百出.所以还是将原文保存在下面供参考吧. master 上写 binlog 是相对轻量的动作(顺序写+会被缓存到操作系统缓存里,轻量与否和磁盘同步设置相关): slave 在主从复制中跟随很紧的情况下,会直接从 master 所在操作系统缓存中读出 binlog 事件:若在几小时或几天后才进行同步则将导致 master 进行读盘操作,耗费相应的 IO 资源: Master_Log_File/Read_Mas

批量造数据程序

批量造数据程序,适用于压力测试,测试数据准备,SQL查询语句优化(需要大量数据)   可一定之进程数,每个进程中开启线程数,已经进程处理的数据量等     Mr. Neo Chen (netkiller), 陈景峰(BG7NYT) <openunix@163.com> 版权 2011, 2012 http://netkiller.github.com 摘要   下面是我多年积累下来的经验总结,整理成文档供大家参考:   Netkiller Architect 手札 Netkiller Linu

Reactor模式详解

前记 第一次听到Reactor模式是三年前的某个晚上,一个室友突然跑过来问我什么是Reactor模式?我上网查了一下,很多人都是给出NIO中的 Selector的例子,而且就是NIO里Selector多路复用模型,只是给它起了一个比较fancy的名字而已,虽然它引入了EventLoop概 念,这对我来说是新的概念,但是代码实现却是一样的,因而我并没有很在意这个模式.然而最近开始读Netty源码,而Reactor模式是很多介绍Netty的文章中被大肆宣传的模式,因而我再次问自己,什么是Reacto

两星级ASP版社区之星编写的ASP常见问题解答

解答|社区|问题 1 CDONTS.NewMail不能发邮件 1 确定已经安装了IIS的SMTP服务. 2 在IIS管理器中,设置smtp服务的属性.在中继对话框里设置"仅除以下列表以外".因为默认情况下它只给某列表中列出的服务器转信,但是这个列表是空的,所以发不出去. 2 无法登陆SQL SERVER 这是因为安装SQL SERVER时使用了NT验证模式,而ASP以匿名身份运行,不够资格访问数据库服务器.解决方法:把SQL SERVER改成混合验证模式(包含SQL验证) 3 ODBC

让Java程序自带JRE

程序   用Java开发程序,发布时总要考虑的问题就是怎么在使用者的机器上装好JRE.要考虑的问题很多:使用者有没有能力独自安装JRE,使用者已有的JRE和我们需要的版本是不是一致,会不会出现版本问题,等等.使用.NET要考虑的问题就少些.现在.NET CLR似乎已经很普及了,看好多D版的Win XP都会自己安装最新的.NET CLR,而且似乎它的安装界面也比JRE友好些.彻底解决安装JRE的问题的方案,就是让我们的应用程序自己背着JRE!这样,我们的程序就像传统的Win32应用程序一样,双击就

ASP中数据库调用中常见错误的现象和解决方法

不能打开注册表关键字(8007000e) Microsoft OLE DB Provider for ODBC Drivers 错误 '8007000e' [Microsoft][ODBC Microsoft Access Driver]常见错误 不能打开注册表关键字 'Temporary (volatile) Jet DSN for process 0x11b4 Thread 0x1a4c DBC 0x9d34354 Jet'. 1.打开数据库时写法不对,标准的ACCESS数据库调用写法: "

ASP中数据库调用常见错误解决

错误|解决|数据|数据库 下面是虚机维护中,经常碰到的一些ASP程序中的数据库调用的错误,现收集整理如下: 不能打开注册表关键字(8007000e) Microsoft OLE DB Provider for ODBC Drivers 错误 '8007000e' [Microsoft][ODBC Microsoft Access Driver]常见错误 不能打开注册表关键字 'Temporary (volatile) Jet DSN for process 0x11b4 Thread 0x1a4