Python 多线程 线程同步 threading.Lock()与自定义简单线程锁方法
业务场景:
对一个项目进行后台监控共有3个check点,每check到一个点的变化就执行编译操作。
业务分析:
1、3个Check点,分别对3个点进行实时轮循检查对比数据变化。如果数据发生变化就执行编译,若未变化则不执行
2、如果某一个Check点检查到数据变化并执行了编译,编译中则其他Check检查到变化则本次不执行编译等待下次轮循检查
demo.py 两种方式解决业务场景问题
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : Benjamin
# @Time : 2020/5/26 14:50
import threading
import random
import time
class testThreads():
def __init__(self):
self.build = 0
def getRandom(self):
a = random.randint(0, 999999)
print(a)
if a < 555555:
print(self.build, "self.build")
if not self.build:
print("du build")
self.build = 1
print("time.sleep(3)")
time.sleep(3)
self.build = 0
def dobuild(self):
while True:
self.getRandom()
threadLock = threading.Lock()
def getRandom():
a = random.randint(0,999999)
print(a)
if a < 555555:
threadLock.acquire() # 加锁
print("du build")
time.sleep(5)
print("time.sleep(5)")
threadLock.release() # 释放锁
testThread = []
# testThreads = testThreads()
for i in range(10):
# Athread = threading.Thread(target=testThreads.dobuild)
Athread = threading.Thread(target=getRandom)
testThread.append(Athread)
# 遍历执行线程组
for t in testThread:
t.setDaemon(True)
t.start()
t.join()
线程同步
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。如下:
多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。
考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。
那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。
锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。
关于线程锁的检查业务场景总结:
1、未加锁 线程特点:无序执行、无线程阻塞、线程加载完毕后同步执行(无等待上一个线程执行完毕后再执行下一个线程)、耗时少执行速度快
2、加锁 线程特点: 有序执行、有线程阻塞、线程加载完毕后依次执行(需等待上一个线程执行完毕后再执行下一个线程)、耗时多
执行速度慢
testPro.pro 正式监控代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : Benjamin
# @Time : 2020/5/18 16:52
import re
import sys
import time
import requests
import threading
from PublicDef import GetHeaderP,GetNowTime
from testJ import buildJenkins,checkBuild
reload(sys)
sys.setdefaultencoding('utf-8')
jenkins_job = sys.argv[1]
def getUrl(jenkins_job):
jenkinsConfig = {
"Test1": ["/diffusion/12/history/master/","/diffusion/12/history/dev/"],
"Test2": ["/diffusion/11/history/master/","/diffusion/10/branches/dev/","/diffusion/11/history/feat_member/"],
"Test3": ["/diffusion/11/history/master/","/diffusion/11/history/dev/","/diffusion/11/history/feat_member/"],
"test": ["test"]
}
urlList = []
for item in jenkinsConfig.get(jenkins_job):
url = "http://172.16.11.235:8070%s"%item
urlList.append(url)
return urlList
def getGitCommit(url):
rsp = requests.get(url=url, headers=GetHeaderP).text
title = re.compile(r'class="phui-oi-link" title="(.*?)">')
titleTxt = re.findall(title, rsp)[0]
href = re.compile(r'<div class="phui-oi-name"><a href="(.*?)" class="phui-oi-link"')
hrefTxt = re.findall(href, rsp)
return titleTxt,hrefTxt
def getDiffGit(url,jenkins_job):
CopyData = ""
print("url:", url)
print("jenkins_job:", jenkins_job)
sys.stdout.flush()
gitName = jenkins_job + " - " + url.split("/")[-2]
while True:
# 获取初始数据
try:
# 获取初始数据
titleTxt, hrefTxt = getGitCommit(url)
except Exception as e:
print(GetNowTime() + " Phabricator login fiald")
print(GetNowTime() + " error: %s"%e)
sys.stdout.flush()
if CopyData != "":
if hrefTxt != CopyData:
print(GetNowTime() + " [%s] new add: %s" %(gitName,titleTxt))
sys.stdout.flush()
time.sleep(3 * 1)
buildJenkins(jenkins_job)
# CopyData = hrefTxt.copy()
CopyData = list(hrefTxt)
else:
print(GetNowTime() + " [%s] no new add, loading check......"%gitName)
sys.stdout.flush()
else:
# CopyData = hrefTxt.copy() # 初始化获取git提交记录
CopyData = list(hrefTxt)
print(GetNowTime() + " begin get [%s] git commit data"%gitName)
sys.stdout.flush()
checkBuild(jenkins_job)
time.sleep(60 * 3)
def addUrlThread(urlList,jenkins_job):
for url in urlList:
Athread = threading.Thread(target=getDiffGit,args=(url,jenkins_job))
Threads.append(Athread)
if __name__ == "__main__":
urlList = getUrl(jenkins_job)
# 初始化线程组为空
Threads = []
# 添加线程组
addUrlThread(urlList,jenkins_job)
# 遍历执行线程组
for t in Threads:
t.setDaemon(True)
t.start()
t.join()
简述:
1、爬虫,抓取html页面获取git提交记录(无git相关权限只有一个页面可以看)。
2、数据对比
3、Python Jenkins操作,自行搜索
4、多线程,线程同步执行检查
Jenkins 集成后的效果:
Run Console: