多线程编程
1 后台&
多线程:
#!/bin/bash
date1=`date +%s`
for i in `seq 1 5`
do
{
echo "sleep 5"
sleep 5
}&
done
wait
date2=`date +%s`
let date3=date2-date1
echo $date3
测试:
单线程:
#!/bin/bash
date1=`date +%s`
for i in `seq 1 5`
do
echo "sleep 5"
sleep 5
done
date2=`date +%s`
let date3=date2-date1
echo $date3
测试:
2 有名管道filo
使用有名管道(fifo)实现每次启动后台进程数量可控
工具:mkfifo
多线程示例
vim test.sh.fifo
#!/bin/bash
tempfifo=$$.fifo #定义管道文件名,$$为本次执行的pid
mkfifo $tempfifo #生成管道文件
exec 12<>$tempfifo #将管道文件与文件描述符12绑定,<读的绑定,>写的绑定,<>则标识对文件描述符1000的所有操作等同于对管道文件$tempfifo的操作,12<>$tempfifo 之间不能有空格,下面都这样
#为什么不直接使用管道文件呢?事实上这并非多此一举,管道的一个重要特性,就是读写必须同时存在,缺失某一个操作,另一个操作就是滞留,而绑定文件的描述符(读、写绑定)正好解决了这个问题
for i in {1..2} #定义每次后台并发线程数,此处为2
do
echo >&12 #对管道输入空行,总行数代表后台并发线程数,为什么是写空行而不是写其它字符?因为管道文件的读取,是以行为单位的
done
#定义测试函数,sleep3秒,每次执行时间为3秒
test(){
sleep 3
}
date1=`date +%s` #开始的时间戳
for i in {1..8} #总任务数8,一次执行时间3秒,正常运行总耗时24秒
do
read -u12 #读取管道中的一行
{
test #调用函数测试
echo $i #输出标识执行状态
echo >&12 #执行完成对管道输入空行,补充本次执行费消耗的空行,空行耗尽,管道阻塞,以此来控制后台并发数
}& #后台执行
done
wait #等待所有后台执行完成
exec 12>&- #取消写绑定
exec 12<&- #取消读绑定
rm -rf $tempfifo #删除管道文件
date2=`date +%s` #完成时间戳
let date3=date2-date1 #时间差
echo "本次执行总耗时:$date3 S"
测试:
bash test.sh.fifo
总耗时:12 s =3*8/2,后台并发数为2
单线程比较
vim test.sh
#!/bin/bash
#定义测试函数,sleep3秒,每次执行时间为3秒
test(){
sleep 3
}
date1=`date +%s` #开始的时间戳
for i in {1..8} #总任务数8,一次执行时间3秒,正常运行总耗时24秒
do
test
echo $i
done
date2=`date +%s` #完成时间戳
let date3=date2-date1 #时间差
echo "本次执行总耗时:$date3 S"
测试:
bash test.sh
总耗时:24 s =3*8