最近看了一些博客研究怎么把单进程的shell脚本改成多进程提升效率,大多数写的都不尽如人意,决定自己写一个
首先看单进程脚本
#!/bin/bash function task { arg=${1} echo "执行任务: ${arg}" # 假设每个任务平均耗时2s sleep 2s } # 一共发布20个任务 for ((i=0; i<20; i++)) do task ${i} done
单进程顺序执行需要耗费40s
再看多进程版本
#!/bin/bash function task { arg=${1} echo "执行任务: ${arg}" # 假设每个任务平均耗时2s sleep 2s } # 创建队列和锁 mkfifo list mkfifo lock # 插入多个数据不阻塞 exec 3<>list exec 4<>lock # 主进程发布任务到队列 for i in {1..20}; do echo ${i} >&3 done # 释放锁 echo >&4 # 开启4个进程 threads=4 for ((i = 0; i < ${threads}; i++)); do { # 获取锁 while read -t 1 -u 4; do if read -t 1 -u 3 arg; then # 释放锁 echo >&4 # 任务代码 task ${arg} fi done } & done wait # 关闭队列和文件描述符 exec 3>&- exec 4>&- rm -rf list rm -rf lock
多进程脚本开启4个子进程同时处理20个任务,一共只需要10s
总结:
1.多进程一个关键点就是fifo队列,从队列中没有读取到数据时进程回阻塞
2.给fifo队列添加文件描述符后,插入数据时不会阻塞
3.进程结束的方式选择了read -t,超时后自动退出,这样做逻辑比较简单,如果用主进程信号通知的方式逻辑比较复杂,没有选择那样实现
4.多进程从同一个fifo队列数据默认会有线程安全问题,为此又用了一个队列lock通过加锁解锁解决
5.文件描述符用完记得关闭