zoukankan      html  css  js  c++  java
  • Shell-使用mkfifo实现多任务并发及并发数控制

    以下为代码实现的一个模拟场景:
    3个生产者,在不断提供服务,处理需求,假设1s处理一个。
    20个消费者,在不断消耗供给产品,提交需求,假设3s消耗一个。

    情景分析:由于消费者的提交需求能力 和 生产者处理需求的能力 不对等,于是出现了供不应求的供销矛盾。

    问题:一般情况下,在供不应求时,会有大量的需求被挂起,也就是排队,排队期间消费者不得离开,否则当前所处的队列顺序就被后面的消费者替代。这样所有排队的消费者都无法干别的事,只能空等,类比操作系统中内存、计算单元等资源被空占,影响整体效率。

    解决思路:通过队列来提前收取需求,类似于自动帮消费者记录排队顺序,这样等轮到自己时,再去执行。那么节省出来的等待时间,就可以去做别的事情,类比操作系统中资源释放。



    #!/bin/bash
    IPLIST=/home/meta/ipinfo/iplist #任务(消费者)
    THREAD=50                              #声明并发线程并发个数,这个是此应用的关键,也就是设置管道的最大任务数
    TMPFIFO=/tmp/$$.fifo               #声明管道名称,'$$'表示脚本当前运行的进程PID
    mkfifo $TMPFIFO                      #创建管道
    exec 5<>${TMPFIFO}               #创建文件标示符“5”,这个数字可以为除“0”、“1”、“2”之外的所有未声明过的字符, 以读写模式操作管道文件;系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变, 换句话说就是在调用进程内部执行一个可执行文件
    rm -rf ${TMPFIFO}               #清除创建的管道文件

    #为并发线程创建同样个数的占位
    for((i=1;i<=$THREAD;i++))
    do
       echo ;     /*借用read命令一次读取一行的特性,使用一个echo默认输出一个换行符,来确保每一行只有一个线程占位;
                    这里让人联想到生产者&消费者模型,管道文件充当消息队列,来记录消费者的需求,然后由生产者去领任务,并完成任务,
                    这里运用了异步解耦的思想*/
    done >&5                
     #将占位信息写入管道

    for i in $(cat ${IPLIST} |grep -viE "^#|备机|ts"|awk '{print $1}')       #从任务队列中依次读取任务
    do
       read -u5        /*从文件描述符管道中,获取一个管道的线程占位然后开始执行操作;read中 -u 后面跟fd,表示从文件描述符中读入,
                               该文件描述符可以是exec新开启的*/
        {
            echo $(cat ~/ipinfo/iplist|grep $i|awk '{print $2}');
            ssh -oConnectTimeout=10 -oConnectionAttempts=3 $i "cd /home/Log/;grep 'MIL' mission_2016-08-03*.log |awk -F, '{if($19==1370) print $0}'|
            awk -F, '{if($20==0) print $0}'>miss_info.txt"
            echo "" >&5    /*任务执行完后在fd5中写入一个占位符,以保证这个线程执行完后,线程继续保持占位,继而维持管道中永远是50个线程数,
                             &表示该部分命令/任务放入后台不占当前的bash,实现并行处理*/
        } &
    done
    wait                #等待父进程的子进程都执行结束后再结束父进程          
    exec 5>&-           #关闭fd5的管道
    exit 0

    例子:

    #!/bin/sh
    
    thread=10
    tmp_fifofile="/tmp/$$.fifo"
    mkfifo $tmp_fifofile
    exec 6<>$tmp_fifofile
    rm $tmp_fifofile
    
    i=1
    while(($i<=$thread))
    do
    echo
    let i=i+1
    done >&6
    
    while read list_pro
    do
      tabnm=`echo  ${list_pro}`
      read -u6
      spooltime=`date +%c`
      { 
        echo ${tabnm} &&{
           sleep 1
        } 
          echo >&6
       }&
    done < list_pro.txt
    
    wait
    exec 6>&-
    list_pro.txt
    [python@master tmp]$ more list_pro.txt 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    可以自己运行试试。。。

    while read tablename
    do
      ftfilename=`echo ${tablename} | awk -F':' '{print $2}'`
      fromsc=`echo ${tablename} | awk -F':' '{print $3}'`
      fromtb=`echo ${tablename} | awk -F':' '{print $4}'`
      tosc=`echo ${tablename} | awk -F':' '{print $5}'`
      totb=`echo ${tablename} | awk -F':' '{print $6}'`
      read -u6
      spooltime=`date +%c`
      #subjob start 
      { 
        sh ${shell_path}/otoelk.sh ${ftfilename} ${dataDate} ${oracle} ${schema_id} ${fromsc} ${fromtb} ${tosc} ${totb} ${confile} ${shell_path} &&{
           sleep 1
        } || { 
           echo "${oracle} to elk sub error"       --出错的时候打印日志
             }
          echo >&6
       }&
    done < ${confile}
  • 相关阅读:
    23种设计模式-原型模式
    23种设计模式-工厂方法模式
    23种设计模式-代理模式
    23种设计模式-装饰模式
    23种设计模式-策略模式
    CSS高度塌陷问题与解决办法
    Java: 多态
    Java: 接口
    Java: 继承
    Java: 单例设计模式
  • 原文地址:https://www.cnblogs.com/hello-wei/p/9507397.html
Copyright © 2011-2022 走看看