shell多线程的必要性:
#shell执行方式:顺序执行,等待前一个完成后,再开始下一条命令
#缺点:串行顺序执行,时间长,不能合理利用系统资源
案例:打印1到10的数字,每隔一秒钟打印一个
一般实现方式:
#/bin/bash
all_num=10
a=$(date +%H%M%S)
for num in seq 1 ${all_num}
do
sleep 1
echo ${num}
done
b=$(date +%H%M%S)
echo -e "开始时间:\t$a"
echo -e "结束时间:\t$b"
多线程方案一:使用&将正在执行的命令放入后台,并重新开启新的shell执行任务
#实现方式:
在linux中,在命令的末尾加上&符号,则表示该命令将在后台执行,这样后面的命令不用等待前面的命令执行完就可以开始执行了。
示例中的循环体内有多条命令,则可以用{}括起来,在大括号后面添加&符号
#缺点:不能保证结果按执行命令的次序输出,即输出次序不可控,并且会出现多循环体乱序的情况
#/bin/bash
all_num=10
a=$(date +%H%M%S)
for num in seq 1 ${all_num}
do
{
sleep 1
echo ${num}
} &
done
b=$(date +%H%M%S)
echo -e "开始时间:\t$a"
echo -e "结束时间:\t$b"
多线程方案二:命令后台运行+wait命令
#实现原理(及缺点):
虽说能保证多个循环体之间不会乱序,但是每个循环体内的依然存在乱序的情况
因为&使得所有循环体内的命令全部进入后台运行,那么倘若循环的次数很多,会使操作系统在瞬间创建出所有的子进程,这会非常消耗系统的资源。
如果循环体内的命令又很消耗系统资源,则结果可想而知
#/bin/bash
all_num=10
a=$(date +%H%M%S)
for num in seq 1 ${all_num}
do
{
sleep 1
echo ${num}
} &
done
wait
b=$(date +%H%M%S)
echo -e "开始时间:\t$a"
echo -e "结束时间:\t$b"
多线程方案三:使用文件描述符控制并发数
#/bin/bash
all_num=10
thread_num=5 #设置并发的进程数
a=$(date +%H%M%S)
#mkfifo
tempfifo="my_temp_fifo"
mkfifo ${tempfifo}
#使文件描述符为非阻塞式
exec 6${tempfifo}
rm -f ${tempfifo}
#为文件描述符创建占位信息
for ((i=1;i&6
#
for num in seq 1 ${all_num}
do
{
read -u6
{
sleep 1
echo ${num}
echo "" >&6
} &
}
done
wait
# 关闭fd6管道
exec 6>&-
b=$(date +%H%M%S)
echo -e "开始时间:\t$a"
echo -e "结束时间:\t$b"
多线程方案四:使用xargs -P控制并发数
#xargs命令有一个-P参数,表示支持的最大进程数,默认为1。为0时表示尽可能地大,即方案2的效果
#/bin/bash
all_num=10
thread_num=5
a=$(date +%H%M%S)
seq 1 ${all_num} | xargs -n 1 -I {} -P ${thread_num} sh -c "sleep 1;echo {}"
b=$(date +%H%M%S)
echo -e "开始时间:\t$a"
echo -e "结束时间:\t$b"
多线程方案五:使用GNU parallel命令控制并发数----暂未验证
#GNU parallel命令是非常强大的并行计算命令,使用-j参数控制其并发数量。
#/bin/bash
all_num=10
thread_num=6
a=$(date +%H%M%S)
parallel -j 5 "sleep 1;echo {}" ::: seq 1 10
b=$(date +%H%M%S)
echo -e "开始时间:\t$a"
echo -e "结束时间:\t$b"
如果文章对你有帮助,欢迎点击上方按钮打赏作者
暂无评论