线程

一、线程

1、启动方法:

方法一:

步骤1、实例化,t1 = threading.Thread(targe=func, args=())

步骤2、t1.start()

例子:

import threading
import time


def run(n):
    print('in the task %s' % n)
    print('当前线程是\033[31;1m%s\033[0m' % threading.current_thread())
    time.sleep(3)


t1 = threading.Thread(target=run, args=(1,))  # 注意args参数最后要加逗号
t2 = threading.Thread(target=run, args=(2,))
t1.start()
t2.start()
print('当前活跃的线程有\033[31;1m%s\033[0m个' % threading.active_count())
print('当前线程是\033[31;1m%s\033[0m' % threading.current_thread())
View Code

方法二:

步骤1、定义一个类,继承threading.Thread,并且重写run

步骤2、使用实例中的start()方法

例子:

import threading
import time


class MyThread(threading.Thread):
    def __init__(self, n):
        super(MyThread, self).__init__()
        self.n = n

    def run(self):
        print('现在在线程%s上' % self.n)
        time.sleep(2)


t1 = MyThread(1)
t2 = MyThread(2)
t1.start()
t2.start()
View Code

 2、统计一个程序所有线程的结束时间:

(1)、原理:使用线程类中的join()方法,此方法阻塞调用线程的执行,直到线程执行完毕。可遍历所有线程的join(),所有线程执行完毕,则开始记录结束时间

(2)、例子:

import threading
import time


def run(n):
    print('这是第\033[1;31m%s\033[0m号线程' % n)
    time.sleep(2)


t_list = []
start_time = time.time()
for i in range(50):
    t = threading.Thread(target=run, args=(i,))
    t.start()
    t_list.append(t)
for thread in t_list:
    thread.join()  # 此处的作用是阻塞调用线程
print('所有线程的运行时间是:\033[1;31m%s\033[0m秒' % (time.time() - start_time))
View Code

 二、守护线程

(1)、概念:主线程启动守护线程,主线程等待非守护线程结束就会结束,无视了守护线程。

(2)、例子:

import threading
import time


def run(n):
    print('这是第\033[1;31m%s\033[0m号线程' % n)
    time.sleep(2)


start_time = time.time()
t_list = []
for i in range(50):
    t = threading.Thread(target=run ,args=(1,))
    t.setDaemon(True)  # 设为守护线程
    t.start()
print('此程序共用时\033[1;31m%s\033[0m秒' % (time.time() - start_time))
View Code

 三、CPython中的GIL:全局解释锁,Python中的线程可放在多个CPU上,但由于这个锁,这使得同一时间就算有多核cpu,也只能有一个线程工作。

四、互斥锁:

(1)、原因:在2.X版本上,就算有了GIL,如果对线程间的共享数据进行访问,线程1可能由于数据还没计算完,但释放了GIL,这样就允许了线程2对其数据进行计算,并且完成。再回到线程1时就继续在寄存器保存的数据上运算,有可能出现数据不准确。

(2)、如果拿到数据的互斥锁,就可对数据修改;否则就不可以。

(3)使用方法:lock = threading.Lock()

加锁 lock.Acquire()

释放锁:lock.Release()

五、递归锁:

(1)用法:用于互斥锁中锁,避免卡死,只需要使用threading.RLock()

(2)、例子:

import threading
lock = threading.RLock()  # 多层锁需要实例化RLock()


def run1():
    global num1
    lock.acquire()
    num1 += 1
    lock.release()
    return num1


def run2():
    global num2
    lock.acquire()  # 第二层锁
    num2 += 1
    lock.release()
    return num2


def run3():
    lock.acquire()  # 第一层锁
    print('在函数run1的结果是', run1())
    print('在函数run2的结果是', run2())
    lock.release()


num1, num2 = 0, 0
for i in range(1):
    t = threading.Thread(target=run3)
    t.start()
while threading.active_count() != 1:
    print('当前激活的线程个数是:', threading.active_count())
print('线程都执行完毕')
View Code

六、信号量(semaphore)

(1)、作用:允许N个线程同时运行,可在实例化时定义。

(2)、例子:

import threading
import time
semaphore = threading.BoundedSemaphore(5)  # 实例化信号量,最多5个线程同时运行


def run(n):
    semaphore.acquire()
    print('Thread %s is working...' % n)
    time.sleep(3)
    semaphore.release()


for i in range(20):
    t = threading.Thread(target=run, args=(i,))
    t.start()
while threading.active_count() != 1:
    pass
print('All task done!')
View Code

 七、threading.event()

1、作用:此类主要用在进程之间的交互,比如说红绿灯,线程红灯亮,则线程车走。。。

2、常用方法:

(1)event.wait():等待设置标志位

(2)event.set():设置标志位

(3)、event.is_set():判断是否设置了标志位

(4)、event.clear():清除标志位

3、例子:

import threading
import time
event = threading.Event()


def light():
    count = 0
    while True:
        if count < 10:
            event.set()  # 设为绿灯
            print('\033[32;1mThe green light is on\033[0m')
        elif (count >= 10) and (count <= 15):
            event.clear()  # 去标识,设为红灯
            print('\033[31;1mThe red light is on\033[0m')
        else:
            count = 0
        count += 1
        time.sleep(1)


def car(name):
    while True:
        if event.is_set():
            print('%s is running' % name)
        else:
            print('%s sees redlight, stop!' % name)
            event.wait()
        time.sleep(1)


light = threading.Thread(target=light)
light.start()
car1 = threading.Thread(target= car, args=('Tesla',))
car1.start()
View Code

 八、队列

1、概念:数据队列是用于存放数据的,与列表不同的是,队列数据取出来后就没有了。并且取数据的顺序主要有三种顺序:先进先出、后进先出、可按优先级取

2、队列类:queue.Queue()、LifoQueue()、PrioprityQueue()

3、共有的方法

(1)、qsize():队列大小

(2)、empty():判断是否为空

(3)、full():判断是否满

(4)、get():按顺序或优先级获取数据

(5)、put():放顺序,注意如果定义的是prioprity队列则可加上优先级、数据组成元组放进去。如put((-3,'Treelight)),数越小优先级越高。

4、例子:生产者和消费者

import threading
import queue
import time
q = queue.Queue(maxsize=10)


def producer():
    count = 0
    while True:
        count += 1
        q.put(count)
        print('我们餐饮已经准备了第%s个包子' % count)
        time.sleep(3)


def consumer(name):
    while True:
        q.get()
        print('%s已经吃了个包子' % name)
        time.sleep(1)


p = threading.Thread(target=producer)
p.start()
c = threading.Thread(target=consumer, args=('Treelight',))
c.start()
View Code

 

转载于:https://www.cnblogs.com/Treelight/p/10915439.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值