zoukankan      html  css  js  c++  java
  • shell多进程

    shell中没有多进程的概念,可以通过开启子shell并在后台执行来实现并发。

        串行执行

    #!/bin/bash
    start=`date +"%s"`
    for (( i=0; i<10; i++ ))
    do
        {
            echo "execute"
            sleep 1
        }
    done
    
    end=`date +"%s"`
    echo "time: " `expr $end - $start`
    12
     
    1
    #!/bin/bash
    2
    start=`date +"%s"`
    3
    for (( i=0; i<10; i++ ))
    4
    do
    5
        {
    6
            echo "execute"
    7
            sleep 1
    8
        }
    9
    done
    10
    11
    end=`date +"%s"`
    12
    echo "time: " `expr $end - $start`

        执行时间为10秒

        

        并发执行

        让for循环中的代码在后台子shell中执行,只需在for循环的结尾加上&,并且在for循环外加上wait语句,等待子进程结束即可。

    #!/bin/bash
    start=`date +"%s"`
    for (( i=0; i<10; i++ ))
    do
        {
            echo "execute"
            sleep 1
        }&
    done
    wait
    end=`date +"%s"`
    echo "time: " `expr $end - $start`
    12
    1
    #!/bin/bash
    2
    start=`date +"%s"`
    3
    for (( i=0; i<10; i++ ))
    4
    do
    5
        {
    6
            echo "execute"
    7
            sleep 1
    8
        }&
    9
    done
    10
    wait
    11
    end=`date +"%s"`
    12
    echo "time: " `expr $end - $start`

        执行时间为1秒,速度提升了10倍。


        这种方式比较简单,但是有个弊端,无法控制子进程的数量,如果循环一万次,会产生一万个子进程,造成不可预期的情况。

        可以通过命名管道来控制子进程的数量

        管道可以用于进程间通信,一个进程向管道中写入数据,同时另一个进程从管道中读取数据,管道为空进程会被阻塞,只有一个进程读或者一个进程写管道时,进程也会被阻塞。

        通常使用的 cat | grep name 中的 | 是无名管道。

         

        利用命令管道控制并发数量的实例

    #!/bin/bash
    
    fd_fifo=/tmp/fd_1  
    mkfifo $fd_fifo      #创建命令管道(pipe类型文件)
    exec 6<>$fd_fifo     #将管道的fd与6号fd绑定
    proc_num=5           #进程个数
    count=0;
    #预分配资源
    for ((i=0;i<$proc_num;i++))
    do
        echo >& 6        #写入一个空行
    done
    
    start=`date +"%s"
    for (( i=0; i<10; i++ ))
    do
      read -u 6          #读取一个空行
      {
          echo "execute"
          sleep 1
          echo >& 6      #完成任务,写入一个空行
      }&                 #后台执行
    done
    wait                 #等待所有的任务完成
    exec 6>&-           #关闭fd 6描述符,stdou和stdin
    exec 6<&-           
    rm -f $fifo          #删除管道
    
    end=`date +"%s"`
    echo "time: " `expr $end - $start`
    x
    1
    #!/bin/bash
    2
    3
    fd_fifo=/tmp/fd_1  
    4
    mkfifo $fd_fifo      #创建命令管道(pipe类型文件)
    5
    exec 6<>$fd_fifo     #将管道的fd与6号fd绑定
    6
    proc_num=5           #进程个数
    7
    count=0;
    8
    #预分配资源
    9
    for ((i=0;i<$proc_num;i++))
    10
    do
    11
        echo >& 6        #写入一个空行
    12
    done
    13
    14
    start=`date +"%s"
    15
    for (( i=0; i<10; i++ ))
    16
    do
    17
      read -u 6          #读取一个空行
    18
      {
    19
          echo "execute"
    20
          sleep 1
    21
          echo >& 6      #完成任务,写入一个空行
    22
      }&                 #后台执行
    23
    done
    24
    wait                 #等待所有的任务完成
    25
    exec 6>&-           #关闭fd 6描述符,stdou和stdin
    26
    exec 6<&-           
    27
    rm -f $fifo          #删除管道
    28
    29
    end=`date +"%s"`
    30
    echo "time: " `expr $end - $start`
    执行时间为2秒(每次有5个进程在同时执行)

    初始化向管道中写入5行空字符
    父shell进程执行read -u 6,会从管道中读取一行,当管道为空时read -u会阻塞,保证最多只有5个shell进程在后台执行。
    子shell进程执行echo >& 6,会向管道中写入一行,父shell进程阻塞状态解除,可以继续开启子shell执行任务。
    父shell进程执行完10次循环后,调用wait函数,等待子shell执行完毕,回收资源。
    如果不加上wait语句,父进程会直接退出,导致子进程成为孤儿进程(孤儿进程为被pid为1的init进程接管);或者子进程提前退出,父进程未执行完但不知道子进程的退出状态,会使子进程成为僵尸进程。

    父进程的变量会被复制一份到子进程中,变量在子进程中的任何修改不会影响父进程中的变量。
  • 相关阅读:
    spring mvc请求过程
    MySQL创建数据库与创建用户以及授权
    单击事件的处理方式及注册窗体的创建之(三)注册窗体的创建流程
    单击事件的处理方式及注册窗体的创建之(二)登录业务逻辑的实现
    单击事件的处理方式及注册窗体的创建之(一)按钮单击事件的实现
    界面优化处理技术之(三)登录框表格组件优化处理
    界面优化处理技术之(二)编辑文本框组件优化处理
    核心技术篇:5.android网络编程之pull解析xml
    核心技术篇:4.android网络通信之sax解析xml
    核心技术篇:3.android网络编程之dom解析xml
  • 原文地址:https://www.cnblogs.com/lolau/p/9647650.html
Copyright © 2011-2022 走看看