《Linux Shell多線程實(shí)現(xiàn)》要點(diǎn):
本文介紹了Linux Shell多線程實(shí)現(xiàn),希望對(duì)您有用。如果有疑問,可以聯(lián)系我們。
shell腳本的執(zhí)行效率雖高,但當(dāng)任務(wù)量巨大時(shí)仍然需要較長的時(shí)間,尤其是需要執(zhí)行一大批的命令時(shí).因?yàn)槟J(rèn)情況下,shell腳本中的命令是串行執(zhí)行的.如果這些命令相互之間是獨(dú)立的,則可以使用“并發(fā)”的方式執(zhí)行這些命令,這樣可以更好地利用系統(tǒng)資源,提升運(yùn)行效率,縮短腳本執(zhí)行的時(shí)間.如果命令相互之間存在交互,則情況就復(fù)雜了,那么不建議使用shell腳原來完成多線程的實(shí)現(xiàn).
為了便利闡述,使用一段測(cè)試代碼.在這段代碼中,通過seq
命令輸出1到10,使用for...in
語句產(chǎn)生一個(gè)執(zhí)行10次的循環(huán).每一次循環(huán)都執(zhí)行sleep 1
,并echo
出當(dāng)前循環(huán)對(duì)應(yīng)的數(shù)字.
注意:
請(qǐng)根據(jù)真實(shí)場(chǎng)景的各種情況理解本文想要表達(dá)的內(nèi)容.
$ cat test1.sh
#/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 "startTime:\t$a"
echo -e "endTime:\t$b"
通過上述代碼可知,為了體現(xiàn)執(zhí)行的光陰,將循環(huán)體開始前后的光陰打印了出來.
運(yùn)行成果:
$ sh test1.sh
10次循環(huán),每次sleep 1秒,所以總執(zhí)行光陰10s.
在linux中,在命令的末尾加上&
符號(hào),則表現(xiàn)該命令將在后臺(tái)執(zhí)行,這樣后面的命令不用等待前面的命令執(zhí)行完就可以開始執(zhí)行了.示例中的循環(huán)體內(nèi)有多條命令,則可以以{}
括起來,在大括號(hào)后面添加&
符號(hào).
$ cat test2.sh
#/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 "startTime:\t$a"
echo -e "endTime:\t$b"
運(yùn)行成果:
sh test2.sh
startTime: 194147
endTime: 194147
[j-tester@merger142 ~/bin/multiple_process]$ 1
2
3
4
5
6
7
8
9
10
通過結(jié)果可知,程序沒有先打印數(shù)字,而是直接輸出了開始和結(jié)束時(shí)間,然后顯示出了命令提示符[j-tester@merger142 ~/bin/multiple_process]$
(出現(xiàn)命令提示符表現(xiàn)腳本已運(yùn)行完畢),然后才是數(shù)字的輸出.這是因?yàn)檠h(huán)體內(nèi)的命令全部進(jìn)入后臺(tái),所以均在sleep了1秒以后輸出了數(shù)字.開始和結(jié)束時(shí)間相同,即循環(huán)體的執(zhí)行時(shí)間不到1秒鐘,這是由于循環(huán)體在后臺(tái)執(zhí)行,沒有占用腳本主進(jìn)程的時(shí)間.
wait
命令辦理上面的問題,只需要在上述循環(huán)體的done語句后面加上wait
命令,該命令等待當(dāng)前腳本進(jìn)程下的子進(jìn)程結(jié)束,再運(yùn)行后面的語句.
$ cat test3.sh
#/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 "startTime:\t$a"
echo -e "endTime:\t$b"
運(yùn)行成果:
$ sh test3.sh
1
2
3
4
5
6
7
9
8
10
startTime: 194221
endTime: 194222
但這樣依然存在一個(gè)問題:
因?yàn)?code>&使得所有循環(huán)體內(nèi)的命令全部進(jìn)入后臺(tái)運(yùn)行,那么倘若循環(huán)的次數(shù)很多,會(huì)使操作系統(tǒng)在瞬間創(chuàng)建出所有的子進(jìn)程,這會(huì)非常消耗系統(tǒng)的資源.如果循環(huán)體內(nèi)的命令又很消耗系統(tǒng)資源,則成果可想而知.
最好的辦法是并發(fā)的進(jìn)程是可配置的.
$ cat test4.sh
#/bin/bash
all_num=10
# 設(shè)置并發(fā)的進(jìn)程數(shù)
thread_num=5
a=$(date +%H%M%S)
# mkfifo
tempfifo="my_temp_fifo"
mkfifo ${tempfifo}
# 使文件描述符為非阻塞式
exec 6<>${tempfifo}
rm -f ${tempfifo}
# 為文件描述符創(chuàng)建占位信息
for ((i=1;i<=${thread_num};i++))
do
{
echo
}
done >&6
#
for num in `seq 1 ${all_num}`
do
{
read -u6
{
sleep 1
echo ${num}
echo "" >&6
} &
}
done
wait
# 關(guān)閉fd6管道
exec 6>&-
b=$(date +%H%M%S)
echo -e "startTime:\t$a"
echo -e "endTime:\t$b"
運(yùn)行成果:
$ sh test4.sh
1
3
2
4
5
6
7
8
9
10
startTime: 195227
endTime: 195229
xargs -P
控制并發(fā)數(shù)xargs命令有一個(gè)-P
參數(shù),表現(xiàn)支持的最大進(jìn)程數(shù),默認(rèn)為1.為0時(shí)表現(xiàn)盡可能地大,即方案2
的效果.
$ cat test5.sh
#/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 "startTime:\t$a"
echo -e "endTime:\t$b"
運(yùn)行成果:
$ sh test5.sh
1
2
3
4
5
6
8
7
9
10
startTime: 195257
endTime: 195259
GNU parallel
命令控制并發(fā)數(shù)GNU parallel
命令是非常強(qiáng)年夜的并行計(jì)算命令,使用-j
參數(shù)控制其并發(fā)數(shù)量.
$ cat test6.sh
#/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 "startTime:\t$a"
echo -e "endTime:\t$b"
運(yùn)行成果:
$ sh test6.sh
1
2
3
4
5
6
7
8
9
10
startTime: 195616
endTime: 195618
“多線程”的好處不言而喻,雖然shell中并沒有真正的多線程,但上述辦理方案可以實(shí)現(xiàn)“多線程”的效果,重要的是,在實(shí)際編寫腳本時(shí)應(yīng)有這樣的考慮和實(shí)現(xiàn).
另外:
方案3、4、5雖然都可以控制并發(fā)數(shù)量,但方案3顯然寫起來太繁瑣.
方案4和5都以非常簡潔的形式完成了控制并發(fā)數(shù)的效果,但由于方案5的parallel命令非常強(qiáng)大,所以十分建議系統(tǒng)學(xué)習(xí)下.
方案3、4、5設(shè)置的并發(fā)數(shù)均為5,實(shí)際編寫時(shí)可以將該值作為一個(gè)參數(shù)傳入.
&
后臺(tái)運(yùn)行本文永久更新鏈接地址:http://www.linuxidc.com/Linux/2017-06/145162.htm
歡迎參與《Linux Shell多線程實(shí)現(xiàn)》討論,分享您的想法,維易PHP學(xué)院為您提供專業(yè)教程。
轉(zhuǎn)載請(qǐng)注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/10711.html