Python多线程threading

进程与线程的区别:

进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。

线程:是进程的一个执行单元,任务调度和执行的基本单位。

区别

  • 在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
  • 所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行。(通过CPU调度,在每个时间片中只有一个线程执行)
  • 内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
  • 包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

P y t h o n Python Python中的多线程:

python中多线程的使用有两种方式:

  • 函数
  • 类包装线程对象

1.函数:
调用threading模块中的
threading.Thread函数来产生新线程。

threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

参数:

  • g r o u p group group
    线程组,默认为None,为以后拓展ThreadGroup类实现而保留。
  • t a r g e t target target
    用于run()方法调用的可调用对象。默认是None,表示不需要调用任何方法。
  • n a m e name name
    线程名称,默认情况下由"Thread-N"构成,其中N为十进制数
  • a r g s args args
    调用目标函数的参数元组
  • k w a r g s kwargs kwargs
    调用目标函数的关键字参数字典
def fun():
	...
	
t1 = threading.Thread(target=fun,name="t1")
t1.start()

2.继承threading.Thread来自定义线程类,本质是重构Thread类中的run方法。(推荐)

class MyThread(threading.Thread):
	def __init__(self,n):
		super(MyThread,self).__init__()
		self.n=n
	def fun(self):
		...
t1 = MyThread("t1")
t1.start()

t r e a d i n g . T h r e a d treading.Thread treading.Thread对象的一些常用方法:

  1. r u n ( ) run() run()
    用以表示线程活动的方法
  2. s t a r t ( ) start() start()
    启动线程活动
  3. j o i n ( [ t i m e ] ) join([time]) join([time])
    等待至线程中止。例如主线程A中,创建了子线程B,并且在主线程A中调用了B.join(),那么,主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行,那么在调用这个线程时可以使用被调用线程的join方法。join([timeout]) 里面的参数时可选的,代表线程运行的最大时间,即如果超过这个时间,不管这个此线程有没有执行完毕都会被回收,然后主线程或函数都会接着执行的,如果线程执行时间小于参数表示的时间,则接着执行,不用一定要等待到参数表示的时间。
  4. i s A l i v e ( ) isAlive() isAlive()
    返回线程是否活动
  5. g e t N a m e ( ) getName() getName()
    返回线程名
  6. s e t N a m e ( ) setName() setName()
    设置线程名
  7. s e t D e a m o n ( ) setDeamon() setDeamon()
    主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(True),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出。这就是setDaemon方法的含义,这基本和join是相反的。此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起,只有等待了所有线程结束它才结束。

threading类的重要函数:

  1. a c t i v e c o u n t ( ) active_count() activecount()
    返回当前存活的线程类 Thread 对象。
  2. c u r r e n t t h r e a d ( ) current_thread() currentthread()
    返回当前对应调用者的控制线程的 Thread 对象。
  3. g e t i d e n t ( ) get_ident() getident()
    返回当前线程的 “线程标识符”。它是一个非零的整数。
  4. e n u m e r a t e ( ) enumerate() enumerate()
    以列表形式返回当前所有存活的 Thread 对象。
  5. m a i n t h r e a d ( ) main_thread() mainthread()
    返回主 Thread 对象。一般情况下,主线程是Python解释器开始时创建的线程。
  6. s t a c k s i z e ( [ s i z e ] ) stack_size([size]) stacksize([size])
    返回创建线程时用的堆栈大小。

1.原始锁(互斥锁)
t h r e a d i n g . L o c k threading.Lock threading.Lock
实现原始锁对象的类。一旦一个线程获得一个锁,会阻塞随后尝试获得此锁的线程,直到它被释放;但任何线程都可以释放它。

lock=threading.Lock() #锁对象
lock.acquire() #关锁
lock.release() #开锁
# acquire和release一般写在run函数里,例如:
# lock.acquire()
# change something...
# lock.release()

2.递归锁(RLock)
互斥锁锁住之后,不管是此线程还是其他线程都不可以再用此锁,而递归锁锁住之后,此进程还可以继续acquire,但其他进程不可以。即此锁支持同一线程中多次请求同一资源。需要注意的是,acquire和release必须成对出现。

缺点:锁住的代码只能以单线程执行;由于可以存在多个锁,不同的线程可以持有不同的锁,试图获得对方持有的锁时,可能会造成死锁。

3.高级锁(threading.Condition())
可以使一个或多个进程等待知道其他线程调度或通知。

wait
该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止。在调用 wait()之前,线程必须要获得该对象的对象监视器锁,即只能在同步方法或同步块中调用 wait()方法。调用wait()方法之后,当前线程会释放锁,直至该线程被Notify()、NotifyAll()或者超时线程又重新获得Lock。

notify(n=1):通知其他线程,那些挂起的线程接到这个通知之后会开始运行,
默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用,
否则会触发RuntimeError。notify()不会主动释放Lock。

notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程(这个一般用得少)
lock_con=threading.Condition([Lock/Rlock]): 锁是可选选项,
默认创建一个RLock(),一般都用默认。

import threading,time
from random import randint
class Producer(threading.Thread):
    def run(self):
        global L
        while True:
            val=randint(0,100)
            # print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
            print('生产者',self.name,' Append'+str(val),L)
            if lock_con.acquire():
                L.append(val)
                lock_con.notify()
                lock_con.release()
            time.sleep(3)
class Consumer(threading.Thread):
    def run(self):
        global L
        while True:
            lock_con.acquire()
            if len(L)==0:
                lock_con.wait()
            print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
            print('消费者',self.name,'Delete'+str(L[0]),L)
            del L[0]
            lock_con.release()
            time.sleep(0.5)
if __name__=='__main__':
    L=[]
    lock_con=threading.Condition()
    threads=[]
    for i in range(5):
        threads.append(Producer())
    threads.append(Consumer())
    for t in threads:
        t.start()
    for t in threads:
        t.join()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值