#!/bin/bash
#by inmoonlight@163.com
#下面的代碼控制並發數。其實是利用令牌原理實現
#一個線程要運行,首先要拿到令牌在該代碼中即read一行數據,讀取不到就會暫停,否則就拿到數據就運行命令,當完成后將令牌放回
#將令牌放回即再在管道文件中寫入一行數據,這里的數據是換行符,echo >&4。這樣另外的線程就可以再讀該數據(拿到令牌)並運行
#!/bin/bash
tmpf=$0.fifo #命名管道
mkfifo $tmpf #創建管道
exec 4<>$tmpf #創建文件描述符4,以讀寫方式操作管道
rm $tmpf #刪除創建的管道
thred=4 #指定並發數
seq=(1 2 3 4 5 6 7 8 9 21 22 23 24 25 31 32 33 34 35) #創建線程的任務列表
#為並發線程創建相應個數的占位
{
for (( i = 1;i<=${thred};i++ ))
do
echo; #因read命令讀取一行,而echo默認輸出換行符,所以為每個線程輸出占位換行
done
} >&4 #將占位寫入管道(輸出給文件描述符4 --> &4 的作用,如果不加 "&" 會被bash解釋為文件名)
for id in ${seq[*]} #從任務列表"seq"按順序獲取任務,或:for id in ${seq}
do
read #讀取一行,即fd4中的一個占位符
(./command ${id}; echo >&4 ) & #在后台執行任務command並將任務${id}賦予當前任務command;執行完成后在fd4中寫入一個換行占位 ,"&" 即將其之前部分放入后台實現並行執行
done <&4 #指定fd4為整個for的stdin(讀取fd4的占位信息)
wait #阻塞等待所有在此腳本中的后台任務:"{.....}&" 完成
exec 4>&- #關閉管道
#以上流程中read、echo對fd4的交替寫和讀是並發處理的關鍵!,可以想象若read讀取不到fd4中數據時將等待fd4