zoukankan      html  css  js  c++  java
  • shell多线程(2)之基于管道实现并发

    在shell脚本里批量执行程序是比较常见的方式,如果程序很多,每个执行时间比较长,则顺序执行需要花费大量的时间。

    此时并发就成为我们考虑的方向。

    上篇《shell多线程》中我们已经简单实现了基于for循环的并发,可以显著提高工作效率;

    缺点是CPU的核心不是无限的,如果全部占用,则会影响系统的正常运行。

    这个时候我们就考虑利用linux系统的管道来进行最大并发数的管控。

    1.举例:

    一个厕所有10个蹲位,如果100个人来使用,则势必形成竞争,这时管理员给每个蹲位一个锁和一把钥匙,先来的人拿钥匙开锁开始使用;

    蹲位全部占满后后面的人等待,当有一个蹲位空出,则交出钥匙给等待队列中的第一个人,如此循环,直到等待队列为空。

    2.文件描述符

    管道具有存一个读一个,读完一个就少一个,没有则阻塞,放回的可以重复取,这正是队列特性,解决这个问题的关键就是文件描述符了。

    3. mkfifo /tmp/fd1     

    创建有名管道文件exec 3<>/tmp/fd1,创建文件描述符3关联管道文件,这时候3这个文件描述符就拥有了管道的所有特性,还具有一个管道不具有的特性:无限存不阻塞,无限取不阻塞,而不用关心管道内是否为空,也不用关心是否有内容写入引用文件描述符: &3可以执行n次echo >&3 往管道里放入n把钥匙

    4.完整代码

    #!/bin/bash
    
    [ -e /tmp/fd1 ] || mkfifo /tmp/fd1 #创建有名管道
    exec 3<>/tmp/fd1                   #创建文件描述符,以可读(<)可写(>)的方式关联管道文件,这时候文件描述符3就有了有名管道文件的所有特性
    rm -rf /tmp/fd1                    #关联后的文件描述符拥有管道文件的所有特性,所以这时管道文件可以删除,我们留下文件描述符来用就可以
    for ((i=1;i<=10;i++))
    do
            echo >&3                   #&3代表引用文件描述符3,这条命令代表往管道里面放入了一个"令牌",文件描述符可以使用0/1/2/225之外的其他数字,这几个已被占用
    done
     
    for ((i=1;i<=100;i++))
    do
    read -u3                           #代表从管道中读取一个令牌
    {
            sleep 1  #sleep 1用来模仿执行一条命令需要花费的时间(可以用真实命令来代替)
            echo 'success'$i       
            echo >&3                   #代表我这一次命令执行到最后,把令牌放回管道
    }&
    done
    wait
     
    exec 3<&-                       #关闭文件描述符的读
    exec 3>&-                       #关闭文件描述符的写

    4.由于从前写的脚本大部分都是以方法的形式存在的,所以想要落地就需要对上面的脚本做一些修改,保证每次循环都会执行一个方法

    t1Fun(){
    echo 1
    }
    t2Fun(){
    echo 2
    }
    t3Fun(){
    echo 3
    }
    t4Fun(){
    echo 4
    }
    [ -e /tmp/fd1 ] || mkfifo /tmp/fd1
    exec 3<>/tmp/fd1
    rm -rf /tmp/fd1
    for ((i=1;i<5;i++))
    do
        echo >&3
    done
    
    for ((i=1;i<=4;i++))
    do 
    read -u3
    {
        sleep 1
        if [ $i -eq 1 ];then
            t1Fun
        elif [ $i -eq 2 ];then
            t2Fun
        elif [ $i -eq 3 ];then
            t3Fun
        else
            t4Fun
        fi
        echo >&3
    }&
    done 
    wait
    
    exec 3<&-
    exec 3>&-
  • 相关阅读:
    docker tar 镜像 容器相互转换
    JavaScript执行上下文
    JavaScript 作用域
    原型与原型链
    使用Navicat for Oracle新建表空间、用户及权限赋予
    PL/SQL Developer使用教程(中文)
    一步一步使用bootstrap开发一个博客模板
    How to create a simple blog using ASP.NET MVC
    一个有意思的编程网站
    一个很好的java编程国外网站
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/9258874.html
Copyright © 2011-2022 走看看