千家信息网

Process的waitFor死锁问题如何解决

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容主要讲解"Process的waitFor死锁问题如何解决",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Process的waitFor死锁问题如何解
千家信息网最后更新 2026年11月02日Process的waitFor死锁问题如何解决

本篇内容主要讲解"Process的waitFor死锁问题如何解决",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Process的waitFor死锁问题如何解决"吧!

Process的waitFor死锁问题

1、发现问题

在实际开发中,进行文件操作时,使用Process对文件进行解压操作,程序执行过程中会出现一直卡在那的问题。

2、原因查找

问题在缓冲区这个地方:可执行程序的标准输出比较多,而运行窗口的标准缓冲区不够大,所以发生阻塞。接着来分析缓冲区,当Runtime对象调用exec(cmd)后,JVM会启动一个子进程,该进程会与JVM进程建立三个管道连接:标准输入,标准输出和标准错误流。假设该程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitfor()这里。

程序运行过程产生等待分析:

(1)、当我们使用Runtime.exec执行命令时,JAVA的线程会创建一个子进程,用于执行命令,而且子进程和JAVA线程会分别独立运行。

(2)、JAVA线程需要等待命令的执行完成,对命令的日志和返回值进行处理,所以在JAVA线程中调用Process.waitFor挂起来等待子进程完成。

(3)、子线程执行时,不断的打印日志信息,我们通过Process.getInputStream和Process.getErrorStream进行获取正常输出日志和错误日志进行处理,也即是读数据。

(4)、这个时候子进程不断的向JAVA线程写入数据,而JAVA线程调用Process.waitFor后已经阻塞挂起,而子进程在不断的向JAVA线程进行写入数据,当我们的Process.getInputStream的buffer缓冲区被写满,JAVA线程依然挂起并未消费buffer中的数据,导致子进程无法继续向buffer缓冲区中继续写入数据,导致子进程也挂起。

(5)、这个时候JAVA线程和子进程都处于挂起的状态,JAVA线程等待子进程的结束,子进程等待JAVA线程对buffer缓冲区中的数据进行消费。两者在相互等待导致死锁。

3、造成死锁原理图

问题代码
public static String cmd(String cmd) throws InterruptedException  {        try {                // 使用Runtime来执行command,生成Process对象                Process process = Runtime.getRuntime().exec(                        new String[] { "/bin/sh", "-c", cmd });                int exitCode = process.waitFor();                // 取得命令结果的输出流                InputStream is = process.getInputStream();                // 用一个读输出流类去读                InputStreamReader isr = new InputStreamReader(is);                // 用缓冲器读行                BufferedReader br = new BufferedReader(isr);                String line = null;                StringBuilder sb = new StringBuilder();                while ((line = br.readLine()) != null) {                    sb.append(line);                }                is.close();                isr.close();                br.close();                                return sb.toString();            } catch (java.lang.NullPointerException e) {                                        throw new BaseException(e);            } catch (java.io.IOException e) {                    throw new BaseException(e);            }            return null;    }

这段代码会产生死锁的原因是, BufferedReader br = new BufferedReader(isr);放在了process.waitFor();之后执行,并不能有效的清空缓冲区,还是会造成缓冲区满,造成阻塞。

解决方案

知道问题原因就号解决了

public static String callCmd(String cmd) throws InterruptedException  {         Process process = null;         BufferedReader normalReader = null;         BufferedReader errorReader = null;         try {                          process = Runtime.getRuntime().exec(                        new String[] { "/bin/sh", "-c", cmd });                /*                    启动读取buffer缓冲区子线程,避免buffer缓冲区被写满,导致线程等待问题                 */                normalReader = new BufferedReader(new InputStreamReader(process.getInputStream()));                errorReader = new  BufferedReader(new  InputStreamReader(process.getErrorStream()));                String line = null;                StringBuilder sb = new StringBuilder();                while ((line = normalReader.readLine()) != null) {                    sb.append(line);                }                String errorLine;                while ((errorLine = errorReader.readLine()) != null) {                    logger.warn("脚本文件执行信息ErrorStream:{}", errorLine);                }                // 等待程序执行结束并输出状态                int exitCode = process.waitFor();                if (0 == exitCode) {                    logger.info("脚本文件执行成功!");                } else {                    logger.error("脚本文件执行失败:{}",cmd);                    throw new BaseException("脚本文件执行失败:"+cmd);                }                return sb.toString();          } catch (java.lang.NullPointerException e) {                throw new BaseException(e);          } catch (java.io.IOException e) {                throw new BaseException(e);          }finally{                if (null != normalReader) {                    try {                        normalReader.close();                    } catch (IOException e) {                        logger.error("流文件关闭异常:", e);                    }                }                if (null != errorReader) {                    try {                        errorReader.close();                    } catch (IOException e) {                        logger.error("流文件关闭异常:", e);                    }                }                if (null != process) {                    process.destroy();                }         }    }

Java中死锁的简单例子及其避免

死锁:当一个线程永远地持有一个锁,并且其他线程都尝试获得这个锁时,那么它们将永远被阻塞。

比如,线程1已经持有了A锁并想要获得B锁的同时,线程2持有B锁并尝试获取A锁,那么这两个线程将永远地等待下去。

我们来看一个死锁的简单例子

public class DeadLockTest{    private static Object A = new Object(), B = new Object();    public static void main(String[] args)    {        new Thread(() -> {            System.out.println("线程1开始执行...");            synchronized (A)            {                try                {                    System.out.println("线程1拿到A锁");                    //休眠两秒让线程2有时间拿到B锁                    Thread.sleep(2000);                } catch (Exception e)                {                    e.printStackTrace();                }                synchronized (B)                {                    System.out.println("线程1拿到B锁");                }            }        }).start();        new Thread(() -> {            System.out.println("线程2开始执行...");            synchronized (B)            {                try                {                    System.out.println("线程2拿到B锁");                    //休眠两秒让线程1有时间拿到A锁                    Thread.sleep(2000);                } catch (Exception e)                {                    e.printStackTrace();                }                synchronized (A)                {                    System.out.println("线程2拿到A锁");                }            }        }).start();    }}

运行结果:

从运行结果可看到,线程1拿到了A锁,并尝试去获取B锁,与此同时线程2拿到了B锁并尝试去获取A锁,此时线程1和线程2就陷入了无限的等待,形成死锁。

那么要怎么预防死锁呢?

下面介绍几个常见方法:

1、避免一个线程同时获取多个锁

2、避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源

3、尝试使用定时锁,使用lock.tryLock来代替使用内置锁。

到此,相信大家对"Process的waitFor死锁问题如何解决"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

线程 进程 死锁 缓冲 缓冲区 问题 数据 文件 标准 输出 命令 程序 尝试 运行 阻塞 不断 日志 脚本 原因 同时 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司的优势 科技互联网公司装修 广州凡科互联网科技 沃里互联网科技 郑州华宇互联网科技 互联网科技大会案例 居家互联网科技有限公司 哈尔滨新华互联网科技 互联网科技公司的市场部门 富国互联网科技创新基金 湖南洣水互联网科技有限公司扣款 小米互联网科技园设置 随着互联网科技发展 昭通云南众福互联网科技有限公司 昊天互联网科技有限公司 互联网科技公司实习生 陕西云淼互联网科技公司 易租星互联网科技有限公司 数字互联网科技有限公司 杭州科技互联网公司有哪些 中关村互联网 科技集团 狮子座互联网科技 互联网科技英文 北京互联网络科技有限公司 极限挑战互联网科技 广州恒生互联网科技有限 科技类公司包括互联网吗 锡山区互联网智能科技产品供应 半导体行业属于互联网高科技类吗 中国主要互联网科技公司
0