shell多线程(2)之基于管道实现并发
在shell脚本里批量执行程序是比较常见的方式,如果程序很多,每个执行时间比较长,则顺序执行需要花费大量的时间。
此时并发就成为我们考虑的方向。
上篇《shell多线程》中我们已经简单实现了基于for循环的并发,可以显著提高工作效率;
缺点是CPU的核心不是无限的,如果全部占用,则会影响系统的正常运行。
这个时候我们就考虑利用linux系统的管道来进行最大并发数的管控。
1.举例:
一个厕所有10个蹲位,如果100个人来使用,则势必形成竞争,这时管理员给每个蹲位一个锁和一把钥匙,先来的人拿钥匙开锁开始使用;
蹲位全部占满后后面的人等待,当有一个蹲位空出,则交出钥匙给等待队列中的第一个人,如此循环,直到等待队列为空。
2.文件描述符
管道具有存一个读一个,读完一个就少一个,没有则阻塞,放回的可以重复取,这正是队列特性,解决这个问题的关键就是文件描述符了。
3. mkfifo /tmp/fd1
创建有名管道文件exec 3<>/tmp/fd1,创建文件描述符3关联管道文件,这时候3这个文件描述符就拥有了管道的所有特性,还具有一个管道不具有的特性:无限存不阻塞,无限取不阻塞,而不用关心管道内是否为空,也不用关心是否有内容写入引用文件描述符: &3可以执行n次echo >&3 往管道里放入n把钥匙
4.完整代码
#!/bin/bash [ -e /tmp/fd1 ] || mkfifo /tmp/fd1 #创建有名管道
exec <>/tmp/fd1 #创建文件描述符,以可读(<)可写(>)的方式关联管道文件,这时候文件描述符3就有了有名管道文件的所有特性
rm -rf /tmp/fd1 #关联后的文件描述符拥有管道文件的所有特性,所以这时管道文件可以删除,我们留下文件描述符来用就可以
for ((i=;i<=;i++))
do
echo >& #&3代表引用文件描述符3,这条命令代表往管道里面放入了一个"令牌",文件描述符可以使用0/1/2/225之外的其他数字,这几个已被占用
done for ((i=;i<=;i++))
do
read -u3 #代表从管道中读取一个令牌
{
sleep #sleep 1用来模仿执行一条命令需要花费的时间(可以用真实命令来代替)
echo 'success'$i
echo >& #代表我这一次命令执行到最后,把令牌放回管道
}&
done
wait exec <&- #关闭文件描述符的读
exec >&- #关闭文件描述符的写
4.由于从前写的脚本大部分都是以方法的形式存在的,所以想要落地就需要对上面的脚本做一些修改,保证每次循环都会执行一个方法
t1Fun(){
echo
}
t2Fun(){
echo
}
t3Fun(){
echo
}
t4Fun(){
echo
}
[ -e /tmp/fd1 ] || mkfifo /tmp/fd1
exec <>/tmp/fd1
rm -rf /tmp/fd1
for ((i=;i<;i++))
do
echo >&
done for ((i=;i<=;i++))
do
read -u3
{
sleep
if [ $i -eq ];then
t1Fun
elif [ $i -eq ];then
t2Fun
elif [ $i -eq ];then
t3Fun
else
t4Fun
fi
echo >&
}&
done
wait exec <&-
exec >&-
shell多线程(2)之基于管道实现并发的更多相关文章
- [shell进阶]——shell多线程
关于shell的多线程 1. 多线程并发执行任务,而不用一台台的串行执行,能更快更高效 2. Shell并没有多线程的概念,所以: * 一般使用wait.read等命令技巧性地模拟多线程实 * 使用命 ...
- 模拟ssh远程执行命令,粘包问题,基于socketserver实现并发的socket
06.27自我总结 1.模拟ssh远程执行命令 利用套接字编来进行远程执行命令 服务端 from socket import * import subprocess server = socket(A ...
- 再谈AbstractQueuedSynchronizer:基于AbstractQueuedSynchronizer的并发类实现
公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...
- 再谈AbstractQueuedSynchronizer3:基于AbstractQueuedSynchronizer的并发类实现
公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...
- Java 并发编程-再谈 AbstractQueuedSynchronizer 3 :基于 AbstractQueuedSynchronizer 的并发类实现
公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...
- Monad、Actor与并发编程--基于线程与基于事件的并发编程之争
将线程.事件.状态等包装成流的源. 核心:解决线程的消耗和锁的效率问题. Java和Node.js可以说分别是基于线程和基于事件的两个并发编程代表,它们互相指责瞧不起对方,让我们看看各种阵营的声音: ...
- 基于socketserver实现并发
基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环 socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题) 一.分析socketserv ...
- scrapy框架基于管道的持久化存储
scrapy框架的使用 基于管道的持久化存储的编码流程 在爬虫文件中数据解析 将解析到的数据封装到一个叫做Item类型的对象 将item类型的对象提交给管道 管道负责调用process_item的方法 ...
- shell多线程,wait
文章来源,wait的使用效果还是不错的 最近在使用shell做一些部署工作,在使用过程中,效率一直不高.想提高效率,经过分析发现,并不是所有操作都是需要串行的,一些操作是可以进行并行操作的.经过学习, ...
随机推荐
- 【Struts2学习笔记(4)】指定需要Struts 2请求后缀的常量定义复杂的过程
一.指定需要Struts 2请求后缀处理 我们是在违约前.action后缀访问Action. 事实上默认后缀是通过不断"struts.action.extension"进行更改.例 ...
- win10 uwp 使用 Matrix3DProjection 进行 3d 投影
原文:win10 uwp 使用 Matrix3DProjection 进行 3d 投影 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 ...
- zlib minizip 实现解压zip
#include <stdio.h> #include <string.h> #include "unzip.h" #define dir_delimter ...
- go语言刷leetcode - 14 Longest Common Prefix
func longestCommonPrefix(strs []string) string { { return "" } { ] } ; ; idx++ { ; i < ...
- 阐述php(五岁以下儿童)
注意事项和使用功能
1.函数声明 <?php /** * function 函数名(參数1, 參数2.... ){ * 函数体; * 返回值; * } */ $sum = sum(3, 4); echo $sum; ...
- c#开发移动APP-Xamarin入门剖析
原文:c#开发移动APP-Xamarin入门剖析 剖析应用程序 Phoneword这个项目是.net标准库项目,它包含所有的共享代码和共享UI. Phoneword.Android这个项目包含Andr ...
- JDBC学习笔记——增删改查
1.数据库准备 要用JDBC操作数据库,第一步当然是建立数据表: ? 1 2 3 4 5 6 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_I ...
- Python抓取小说
Python抓取小说 前言 这个脚本命令MAC在抓取小说写,使用Python它有几个码. 代码 # coding=utf-8 import re import urllib2 import chard ...
- react项目实践——(3)babel
1. babel Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行. (1)安装 npm install --save-dev babel-core babel-e ...
- nyoj 92 图片实用面积【bfs】
图像实用区域 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描写叙述 "ACKing"同学曾经做一个图像处理的项目时.遇到了一个问题,他须要摘取出图片中某 ...