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 集成后的效果:

python如何监控当前线程的运行状态 python多线程监听_git

 

Run Console:

python如何监控当前线程的运行状态 python多线程监听_线程组_02