专栏首页有趣的django11.多线程、多进程和线程池编程

11.多线程、多进程和线程池编程

1.1.线程同步Lock和Rlock

(1)Lock

  • 用锁会影响性能
  • 用锁会产生死锁
import threading
from threading import Lock

total = 0
lock = Lock()

def add():
    global total
    global local
    for i in range(100000):
        lock.acquire()
        # lock.acquire()   #如果再加把锁会产生死锁
        total += 1
        lock.release()

def desc():
    global total
    global local
    for i in range(100000):
        lock.acquire()     #获取锁
        total -= 1
        lock.release()     #释放锁

thread1 = threading.Thread(target=add)
thread2 = threading.Thread(target=desc)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(total)   #0

(2)RLock

RLock:在同一个线程里面,可以连续多次调用acquire,一定要注意acquire和release的次数相等

import threading
from threading import Lock,RLock

total = 0
lock = RLock()

def add():
    global total
    global local
    for i in range(100000):
        #用RLock在同一线程里面,可以多次调用acquire,不会产生死锁
        lock.acquire()
        lock.acquire()
        total += 1
        #release的次数和acquire的次数相等
        lock.release()
        lock.release()

def desc():
    global total
    global local
    for i in range(100000):
        lock.acquire()     #获取锁
        total -= 1
        lock.release()     #释放锁

thread1 = threading.Thread(target=add)
thread2 = threading.Thread(target=desc)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(total)   #0

1.2.线程同步 - condition 

使用condition模拟对话

import threading
from threading import Condition

 #通过condition,完成协同读诗
class XiaoAi(threading.Thread):
    def __init__(self,cond):
        super().__init__(name='小爱')
        self.cond = cond

    def run(self):
        with self.cond:
            #等待
            self.cond.wait()
            print("{} : 在".format(self.name))
            #通知
            self.cond.notify()

            self.cond.wait()
            print("{} : 好啊".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{} : 君住长江尾".format(self.name))
            self.cond.notify()

class TianMao(threading.Thread):
    def __init__(self,cond):
        super().__init__(name="天猫精灵")
        self.cond = cond

    def run(self):
        with self.cond:
            print("{} : 小爱同学".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 我们来对古诗吧".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 我在长江头".format(self.name))
            self.cond.notify()
            self.cond.wait()

if __name__ == '__main__':
    cond = threading.Condition()
    xiaoai = XiaoAi(cond)
    tianmao = TianMao(cond)

    xiaoai.start()
    tianmao.start()

结果:

1.3.线程同步 - Semaphore 

控制线程并发数量

#samaphore是用于控制进入数量的锁

import threading
import time

class htmlSpider(threading.Thread):
    def __init__(self,url,sem):
        super().__init__()
        self.url = url
        self.sem = sem

    def run(self):
        time.sleep(2)
        print("got html text success!")
        self.sem.release()   #释放锁

class UrlProducer(threading.Thread):
    def __init__(self, sem):
        super().__init__()
        self.sem = sem
    def run(self):
        for i in range(20):
            self.sem.acquire()    #加锁
            html_htread = htmlSpider("baidu.com/{}".format(i), self.sem)
            html_htread.start()

if __name__ == '__main__':
    #控制线程并发数量为3
    sem = threading.Semaphore(3)
    url_producer = UrlProducer(sem)
    url_producer.start()

11.4.ThreadPoolExecutor线程池

线程池

from concurrent.futures import ThreadPoolExecutor, as_completed
import time

#为什么要线程池
#主线程中可以获取某一个线程的状态或者某一个任务的状态,以及返回值
#当一个线程完成的时候,主线程立马知道
#futures可以让多线程和多进程编码接口一致

def get_html(times):
    time.sleep(times)
    print("get page {} success".format(times))
    return times

executor = ThreadPoolExecutor(max_workers=2)

#通过submit提交执行的函数到线程池中,sumbit是立即返回
task1 = executor.submit(get_html, (3))    #函数和参数

#done方法用于判定某个任务是否完成
print(task1.done())      #False
time.sleep(4)
print(task1.done())      #True
#result方法查看task函数执行的结构
print(task1.result())    #3

用as_completed获取任务结束的返回

from concurrent.futures import ThreadPoolExecutor, as_completed
import time

#为什么要线程池
#主线程中可以获取某一个线程的状态或者某一个任务的状态,以及返回值
#当一个线程完成的时候,主线程立马知道
#futures可以让多线程和多进程编码接口一致

# def get_html(times):
#     time.sleep(times)
#     print("get page {} success".format(times))
#     return times
#
# executor = ThreadPoolExecutor(max_workers=2)
#
# #通过submit提交执行的函数到线程池中,sumbit是立即返回
# task1 = executor.submit(get_html, (3))    #函数和参数
#
# #done方法用于判定某个任务是否完成
# print(task1.done())      #False
# time.sleep(4)
# print(task1.done())      #True
# #result方法查看task函数执行的结构
# print(task1.result())    #3

def get_html(times):
    time.sleep(times)
    print("get page {} success".format(times))
    return times

executor = ThreadPoolExecutor(max_workers=2)

#获取已经成功的task的返回
urls = [3,2,4]
all_task = [executor.submit(get_html, (url)) for url in urls]

for future in as_completed(all_task):
    data = future.result()
    print(data)   #已经成功的task函数的return

11.5.进程间通信 - Queue

Queue

import time

from multiprocessing import Process, Queue

def producer(queue):
    queue.put("a")
    time.sleep(2)

def consumer(queue):
    time.sleep(2)
    data = queue.get()
    print(data)

if __name__ == '__main__':
    queue = Queue(10)
    my_producer = Process(target=producer, args=(queue,))
    my_consumer = Process(target=consumer, args=(queue,))

    my_producer.start()
    my_consumer.start()
    my_producer.join()
    my_consumer.join()

11.6.进程间通信 - Manager

Manger

import time

from multiprocessing import Process, Queue, Manager,Pool

def producer(queue):
    queue.put("a")
    time.sleep(2)

def consumer(queue):
    time.sleep(2)
    data = queue.get()
    print(data)

if __name__ == '__main__':
    #pool中的进程间通信需要使用manger中的queue
    queue = Manager().Queue(10)
    pool = Pool(2)   #创建进程池

    pool.apply_async(producer, args=(queue, ))
    pool.apply_async(consumer, args=(queue, ))

    pool.close()
    pool.join()

11.7.进程间通信 - Pipe

pipe实现进程间通信(只能两个进程之间)

#Pipe进程间通信
from multiprocessing import Process, Pipe

def producer(pipe):
    pipe.send("derek")

def consumer(pipe):
    print(pipe.recv())

if __name__ == '__main__':
    receive_pipe, send_pipe = Pipe()
    my_producer = Process(target=producer, args=(send_pipe, ))
    my_consumer = Process(target=consumer, args=(receive_pipe, ))

    my_producer.start()
    my_consumer.start()
    my_producer.join()
    my_producer.join()

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Qt多线程编程之线程池

    线程的创建及销毁需要与系统交互,会产生很大的开销。若需要频繁的创建线程建议使用线程池,有线程池维护一定数量的线程,当需要进行多线程运算时将运算函数传递给线程池即...

    DeROy
  • Java多线程和线程池

    在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际...

    全栈程序员站长
  • Java多线程和线程池

    在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际...

    Java编程指南
  • .Net多线程编程—Parallel LINQ、线程池

    Parallel LINQ 1 System.Linq.ParallelEnumerable 重要方法概览: 1)public static ParallelQ...

    甜橙很酸
  • Java 多线程编程(聊聊线程池)

    线程是一种昂贵的系统资源,其“昂贵”不仅在于创建线程所需要的资源开销,还在于使用过程中带来的资源消耗。一个系统能够支持同时运行的线程总数受限于该系统所拥有的处理...

    业志陈
  • [linux] 多进程和多线程

    1.在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种”昂贵”的多任务工作方式。 2.而...

    陶士涵
  • JUC 多线程 线程池

    线程池主要是控制运行线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量的线程排队等候,等其他线程执行完毕,再从队列中...

    万能青年
  • JUC并发编程(一)多线程使用和线程池

    一个进程往往可以包含多个线程,至少包含一个! Java默认有几个线程? 2 个: mian、GC 对于Java而言:Thread、Runnable、Callab...

    HcodeBlogger
  • 多线程与多进程 | 多线程

    是计算机中已运行程序的实体。进程与程序不同,程序本身只是指令、数据及其组织形式的描述,进程才是程序的真正运行的实体。

    数据STUDIO
  • 多线程编程学习十(线程池原理).

    tips:这样的设计方案,可以避免频繁的线程创建,大部分的工作任务都会停留在第二步。

    JMCui
  • 线程、进程、多线程、多进程和多任务有啥关系?

    进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。

    杰哥的IT之旅
  • 多线程之线程池(三)

    OPice
  • C#多线程(12):线程池

    线程池全称为托管线程池,线程池受 .NET 通用语言运行时(CLR)管理,线程的生命周期由 CLR 处理,因此我们可以专注于实现任务,而不需要理会线程管理。

    痴者工良
  • 多进程与多线程 | 多进程

    Python提供了multiprocessing。multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模...

    数据STUDIO
  • 多线程编程学习五(线程池的创建)

    一、概述 New Thread的弊端如下:        a、每次New Thread新建对象性能差。        b、线程缺乏统一的管理,可能无限制的新建...

    JMCui
  • python多线程和多进程(二)

    1、multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。

    py3study
  • python socket多线程和多进程

    在socket中,如果直接创建的话,是只能接受一个用户的请求 需要实现socketserver中的handle方法,可以实现多进程并发访问

    py3study
  • Python第十二章-多进程和多线程02-多线程

    MySQL被Sun收购后,搞了个过渡的6.0版本,没多久就下线了(有一次居然听说有人在线上用6.0版本,我惊得下巴都掉了)。被Oracle收购后,终于迎来了像样...

    不会飞的小鸟
  • Java 多线程(6)----线程池(上)

    在前面的系列文章中,我们介绍了一下 Java 中多线程的一些主要的知识点和多线程并发程序的设计和处理思想。包括线程的介绍、生命周期、线程的运行控制。之后介绍了如...

    指点

扫码关注云+社区

领取腾讯云代金券