前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >力扣1114.按序打印——Python解决并发问题的10种思路

力扣1114.按序打印——Python解决并发问题的10种思路

作者头像
才浅Coding攻略
发布2022-12-12 17:14:23
2280
发布2022-12-12 17:14:23
举报
文章被收录于专栏:才浅coding攻略才浅coding攻略

方法一:while循环法

这个解法用于理解多线程的阻塞,相当于先用某些方法卡住执行顺序,然后不断监控目标,直到目标符合条件时才跳出当前断点继续执行后续语句。

代码语言:javascript
复制
class Foo:
    def __init__(self):
        self.t = 0

    def first(self, printFirst: 'Callable[[], None]') -> None:   
        printFirst()
        self.t = 1

    def second(self, printSecond: 'Callable[[], None]') -> None:
        while self.t != 1:
            pass
        printSecond()
        self.t = 2

    def third(self, printThird: 'Callable[[], None]') -> None:
        while self.t != 2:
            pass  
        printThird()

while会跑满CPU影响GIL上下文切换的判定,可以加入time.sleep,将CPU交还给GIL,及时切换线程。

方法二:time.sleep睡眠法

代码语言:javascript
复制
from time import sleep
class Foo:
    def __init__(self):
        self.t = 0

    def first(self, printFirst: 'Callable[[], None]') -> None:   
        printFirst()
        self.t = 1

    def second(self, printSecond: 'Callable[[], None]') -> None:
        while self.t != 1:
            sleep(1e-3)
        printSecond()
        self.t = 2

    def third(self, printThird: 'Callable[[], None]') -> None:
        while self.t != 2:
            sleep(1e-3)  
        printThird()

方法三:with Condition条件对象法

调用了threading模块里的Condition方法,启动wait_for阻塞每个函数,达到各个函数对应的目标值才释放线程;with用来替代try语句,with是配合Condition方法常用的语法糖。

代码语言:javascript
复制
import threading

class Foo:
    def __init__(self):
        self.c = threading.Condition()
        self.t = 0

    def first(self, printFirst: 'Callable[[], None]') -> None:
        self.res(0, printFirst)

    def second(self, printSecond: 'Callable[[], None]') -> None:
        
        self.res(1, printSecond)

    def third(self, printThird: 'Callable[[], None]') -> None:
        
        self.res(2, printThird)

    def res(self, val: int, func: 'Callable[[], None]') -> None:
        with self.c:
            self.c.wait_for(lambda: val == self.t)  # 参数是函数对象,返回值是bool类型
            func()
            self.t += 1
            self.c.notify_all()

方法四:Lock锁对象法

初始化时添加acquire进行阻塞,调用其他函数的时候按顺序release释放。

代码语言:javascript
复制
import threading

class Foo:
    def __init__(self):
        self.l1 = threading.Lock()
        self.l1.acquire()
        self.l2 = threading.Lock()
        self.l2.acquire()

    def first(self, printFirst: 'Callable[[], None]') -> None:
        printFirst()
        self.l1.release()

    def second(self, printSecond: 'Callable[[], None]') -> None:
        self.l1.acquire()
        printSecond()
        self.l2.release()

    def third(self, printThird: 'Callable[[], None]') -> None:
        self.l2.acquire()
        printThird()

方法五:Semaphore信号量对象法

和Lock方法类似,不过在类赋值的时候可以带有参数自带阻塞。

代码语言:javascript
复制
import threading

class Foo:
    def __init__(self):
        self.s1 = threading.Semaphore(0)
        self.s2 = threading.Semaphore(0)

    def first(self, printFirst: 'Callable[[], None]') -> None:
        printFirst()
        self.s1.release()

    def second(self, printSecond: 'Callable[[], None]') -> None:
        self.s1.acquire()
        printSecond()
        self.s2.release()

    def third(self, printThird: 'Callable[[], None]') -> None:
        self.s2.acquire()
        printThird()

方法六:Event事件对象法

原理也是添加阻塞,然后释放线程,和Lock和Semaphore一样,不过event用wait方法作为阻塞,用set来释放线程,默认类赋值就是阻塞的。

代码语言:javascript
复制
import threading

class Foo:
    def __init__(self):
        self.e1 = threading.Event()
        self.e2 = threading.Event()

    def first(self, printFirst: 'Callable[[], None]') -> None:
        printFirst()
        self.e1.set()

    def second(self, printSecond: 'Callable[[], None]') -> None:
        self.e1.wait()
        printSecond()
        self.e2.set()

    def third(self, printThird: 'Callable[[], None]') -> None:
        self.e2.wait()
        printThird()

方法七:Barrier栅栏对象法

Barrier初始化的时候定义了parties = 2个等待线程,调用完了parties个wait就会释放线程。

代码语言:javascript
复制
import threading

class Foo:
    def __init__(self):
        self.b1 = threading.Barrier(2)
        self.b2 = threading.Barrier(2)

    def first(self, printFirst: 'Callable[[], None]') -> None:
        printFirst()
        self.b1.wait()

    def second(self, printSecond: 'Callable[[], None]') -> None:
        self.b1.wait()
        printSecond()
        self.b2.wait()

    def third(self, printThird: 'Callable[[], None]') -> None:
        self.b2.wait()
        printThird()

方法八:Queue队列法

当队列为空时,get方法就会自动阻塞,直到put使之非空才会释放进程。

代码语言:javascript
复制
import queue

class Foo:
    def __init__(self):
        self.q1 = queue.Queue()
        self.q2 = queue.Queue()

    def first(self, printFirst: 'Callable[[], None]') -> None:
        printFirst()
        self.q1.put(0)

    def second(self, printSecond: 'Callable[[], None]') -> None:
        self.q1.get()  # Remove and return an item from the queue.
        printSecond()
        self.q2.put(0)  # Put an item into the queue

    def third(self, printThird: 'Callable[[], None]') -> None:
        self.q2.get()
        printThird()

方法九:定长队列法

对于定长队列来说,如果队列已满,那么put方法也是阻塞。

代码语言:javascript
复制
import queue

class Foo:
    def __init__(self):
        self.q1 = queue.Queue(1)
        self.q1.put(0)
        self.q2 = queue.Queue(1)
        self.q2.put(0)

    def first(self, printFirst: 'Callable[[], None]') -> None:
        printFirst()
        self.q1.get()

    def second(self, printSecond: 'Callable[[], None]') -> None:
        self.q1.put(0)
        printSecond()
        self.q2.get()

    def third(self, printThird: 'Callable[[], None]') -> None:
        self.q2.put(0)
        printThird()

方法十:字典法

初始化一个空字典,根据键存储对应的函数作为字典的值,当字典长度为3时,按序输出字典。由于该方法集中在最后一个线程进行输出,力扣目前不通过。

代码语言:javascript
复制
class Foo:
    def __init__(self):
        self.d = {}

    def first(self, printFirst: 'Callable[[], None]') -> None:
        self.d[0] = printFirst
        self.res()
        
    def second(self, printSecond: 'Callable[[], None]') -> None:
        self.d[1] = printSecond
        self.res()
        
    def third(self, printThird: 'Callable[[], None]') -> None:
        self.d[2] = printThird
        self.res()
        
    def res(self) -> None:
        if len(self.d) == 3:
            self.d[0]()
            self.d[1]()
            self.d[2]()
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 才浅coding攻略 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档