shell中的wait命令及并发的实现{}&

sleep 和wait

在 shell 中使用 wait 是在等待上一批或上一个脚本执行完(即上一个的进程终止),再执行wait之后的命令。
sleep是使系统休眠一定的时间之后再去执行下面的任务。

语法

wait [进程号或作业号]

wait 22	  等待22进程完在执行下面的
wait %1  第一个作业

如果wait后面不带任何的进程号或作业号,那么wait会直至当前shell中进程的所有子进程都执行结束后,才继续执行下一步。

实例

等待所有后台进程结束


[root@server1 mnt]# cat wait.sh 
sleep 10 &
sleep 5 &
wait
[root@server1 mnt]# time sh wait.sh 

real	0m10.007s		/可见等待了10s后才结束
user	0m0.001s
sys	0m0.005s

等待上个进程结束

$! 表示上一个子进程的进程号,

#!/bin/bash
sleep 10 &
sleep 5 &
wait $!
[root@server1 mnt]# time sh wait.sh 

real	0m5.005s		/可见等待上一个进程只要5s
user	0m0.001s
sys	0m0.003s

shell脚本多线程


#!/bin/bash
 
start_time=$(date +%s)
 
for ((i=1;i<=1000;i++))
do
{
sleep 5s	/该命令是用来测试的命令,此处为实际执行的命令
echo "$i"
} &

done
wait 	/等待1000个后台任务全都执行完成之后,再继续执行执行脚本
 
end_time=$(date +%s) 
echo "TIME:$(expr $end_time- $start_time)"

用{}把循环体括起来,后加一个&符号,代表每次循环都把命令放入后台运行,一旦放入后台,就意味着{}里面的命令交给操作系统的一个线程处理了,循环了1000次,就有1000个&把任务放入后台,操作系统会并发1000个线程来处理.

运行结果:
在这里插入图片描述

控制线程的数量

使用linux管道文件特性制作队列,控制线程数目。

管道文件:

无名管道(ps aux | grep nginx)
有名管道(mkfifo /tmp/fd1)

原理:
一个女士公共厕所总共就10个蹲位,这个蹲位就是队列长度,女侧所门口放着10把钥匙,要想上厕所必须拿一把钥匙,上完厕所后归还钥匙,下一个人就可以拿钥匙进去上厕所了,这样同时来了1千为美女上厕所,那前十个人抢到钥匙进去上厕所了,后面的990人需要等一个出来归还钥匙才可以拿到钥匙进去上厕所,这样10把钥匙就实现了控制1000人上厕所的任务,(os中称之为信号量)

二.文件描述符

1.管道具有存一个读一个,读完一个就少一个,没有则阻塞,放回的可以重复取,这正是队列特性,但是问题是当往管道文件里面放入一段内容,没人取则阻塞,这样你永远也没办法往管道里面同时放入10段内容(想当与10把钥匙),解决这个问题的关键就是文件描述符了。

2.mkfifo /tmp/fd1

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

#!/bin/bash
start_time=`date +%s`              /定义脚本运行的开始时间
[ -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,这条命令代表往管道里面放入了一个"令牌"
done		/一共放了10个令牌
 
for ((i=1;i<=1000;i++))
do
read -u3                         /代表从管道中读取一个令牌
{
        sleep 1  	/sleep 1用来模仿执行一条命令需要花费的时间(可以用真实命令来代替)
        echo 'success'$i       
        echo >&3                   /代表我这一次命令执行到最后,把令牌放回管道
}&
done
wait
 
stop_time=`date +%s`  #定义脚本运行的结束时间
 
echo "TIME:`expr $stop_time - $start_time`"
exec 3<&-                       /关闭文件描述符的读
exec 3>&-                       /关闭文件描述符的写

运行:
在这里插入图片描述
可见10个并发共运行10秒。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值