0
点赞
收藏
分享

微信扫一扫

Shell之多线程

单线程案例:

​cat 1.sh​

#!/bin/bash
date
for i in `seq 1 10`
do
echo 'sleep 5'
sleep 5
done
date

​sh 1.sh​​ 输出:

Wed Feb 23 11:22:00 CST 2022
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
Wed Feb 23 11:22:50 CST 2022

案例说明:脚本按顺序处理10个需求,每个需求处理时长为5秒钟,单线程处理预期耗时为10*5=50s。结果符合预期。

适用场景:前后任务存在依赖。该案例前后任务不存在依赖,可以使用多线程方法减少耗时。


多线程改造案例:

​cat 2.sh​

#!/bin/bash
date
for i in `seq 1 10`
do
{
echo 'sleep 5'
sleep 5
} &
done
wait
date

​sh 2.sh​

Wed Feb 23 11:29:30 CST 2022
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
Wed Feb 23 11:29:35 CST 2022

案例说明:改造案例一的脚本,原理是借用​for循环​,将任务块​{...}添加​&后缀​的方式​置为后台运行,再使用​wait命令等后台任务执行完成后结束脚本状态。

适用于预期任务并发少的场景。

优点:所有任务可以同时处理,耗时短;                                                  缺点:如果任务并发较多,超出系统负载会导致任务失败和服务器性能不稳定等问题。

如何解决并发较多、不可控?                                                                  答:预设并发数量,把任务以队列的方式在预设并发内进行处理。

多线程可控并发案例:

​cat 3.sh​

#!/bin/bash
date

function my_task() {
echo "sleep 5"
sleep 5
}

fifofile="/tmp/$$.fifo"
mkfifo $fifofile
exec 6<>$fifofile
rm -rf $fifofile

thread_num=5
job_num=20

for ((i=0;i<${thread_num};i++)); do
echo >&6
done

for ((i=0;i<${job_num};i++)); do
read -u6
{
my_task
} &
echo >&6
done

wait
exec 6<&-
exec 6>&-

date

​sh 3.sh​

Wed Feb 23 12:05:00 CST 2022
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
Wed Feb 23 12:05:05 CST 2022

案例说明:解决并发不可控问题,预设并发为5个;任务块为my_task函数,测试任务数为20个;

脚本逻辑:

第一块代码:定义任务,放入函数中,方便下面调用。

第二块代码:定义并发使用的通道。创建一个管道文件$$.fifo,并将管道文件定义到6号文件描述符(扩展:了解exec和文件描述符,这里的文件描述符可以自行定义,<是读取、>是写入,<>是读写),意思是用6号文件描述符代替管道文件,所有这里将失效的管道文件删除。

第三块代码:预设可用并发数量,预期任务数量。

第四块代码:在6号文件描述符中创建并发位置,注意>和&中间没有空格。

第五块代码:创建任务队列,使用read读取并发位置,执行任务后再执行echo补充上面读取的并发位。

第六块代码:wait等待所有后台任务执行完成再执行下一步,下面两步分别是关闭读取和写入6号文件描述,这里关闭读写需要分两步操作。

举报

相关推荐

0 条评论