python创建线程

1、方法一:通过实例化threading.Thread类来创建线程,程序实例化了三个Thread类的实例,并向任务函数传递不同的参数,使它们运行不同的时间后结束,start()方法开启线程,join()方法阻塞主线程,等待当前线程运行结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import time
import threading
def task_thread(counter):
    print(f'线程名称:{threading.current_thread().name} 参数: {counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M%S")}')
    num=counter
    while num:
        time.sleep(3)
        num-=1
    print(f'线程名称:{threading.current_thread().name} 参数:{counter} 结束时间:{time.strftime("%Y-%m-%d %H:%M%S")}')
 
if __name__=="__main__":
    print(f'主线程开始的时间是:{time.strftime("%Y-%m-%d %H:%M:%S")}')
    #初始化三个线程,传递不同的参数
    t1=threading.Thread(target=task_thread,args=(3,))
    t2=threading.Thread(target=task_thread,args=(2,))
    t3 = threading.Thread(target=task_thread, args=(1,))
    #start()方法开启三个线程
    t1.start()
    t2.start()
    t3.start()
    #等待运行结束,join()方法阻塞主线程,等待当前线程运行结束
    t1.join()
    t2.join()
    t3.join()
 
    print(f'主线程结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')

 2、方法二:继承Thread类,在子类中重写run()和init()类

通过继承Thread类创建线程,以下程序自定义线程类MyThreading,继承自threading.Thread,并重写了__init__()方法和run()方法。其中run()方法相当于方法一中的任务函数,运行结果与方法一中的结果一致。

复制代码
import time
import threading

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

    def run(self):
        print(f'线程名称:{threading.current_thread().name} 参数: {self.counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M%S")}')
        counter=self.counter
        while counter:
            time.sleep(3)
            counter-=1
        print(f'线程名称:{threading.current_thread().name} 参数: {self.counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M%S")}')

if __name__=="__main__":
    print(f'主线程开始的时间是:{time.strftime("%Y-%m-%d %H:%M:%S")}')
    #初始化三个线程,传递不同的参数
    t1=MyThread(3)
    t2=MyThread(2)
    t3=MyThread(1)
    #start()方法开启三个线程
    t1.start()
    t2.start()
    t3.start()
    #等待运行结束,join()方法阻塞主线程,等待当前线程运行结束
    t1.join()
    t2.join()
    t3.join()
    print(f'主线程结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
复制代码

 如果继承Thread类,想调用外部传入函数,请看下面示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import time
import threading
 
def task_threading(counter):
    print(f'线程名称:{threading.current_thread().name} 参数:{counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
    num=counter
    while num:
        time.sleep(3)
        num-=1
    print(f'线程名称:{threading.current_thread().name} 参数:{counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
 
class MyThread(threading.Thread):
    def __init__(self,target,args):
        super().__init__()
        self.target=target
        self.args=args
 
    def run(self):
       self.target(*self.args)
 
if __name__=="__main__":
    print(f'主线程开始的时间是:{time.strftime("%Y-%m-%d %H:%M:%S")}')
    #初始化三个线程,传递不同的参数
    t1=MyThread(target=task_threading,args=(3,))
    t2=MyThread(target=task_threading,args=(2,))
    t3=MyThread(target=task_threading,args=(1,))
    #start()方法开启三个线程
    t1.start()
    t2.start()
    t3.start()
    #等待运行结束,join()方法阻塞主线程,等待当前线程运行结束
    t1.join()
    t2.join()
    t3.join()
    print(f'主线程结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')

  通过self.target来接收外部传入的函数,通过self.args来接收外部函数的参数,这样就可以使用继承Thread的线程类调用外部传入的函数。

 

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,这时候就需要互斥锁来进行同步,例如,在三个线程对共同变量num进行100万次加减操作后,其num的结果不为0.为了保证数据的正确性,需要使用互斥锁对多个线程进行同步,限制当一个线程正在访问数据时,其他只能等待,直到前一线程释放锁。使用threading.Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire和release方法,对于每次只运行一个线程操作的数据,可以将其操作放到acquire方法和release方法之间。

复制代码
import time
import threading
num=0
lock=threading.Lock()
def task_threading(n):
    global num
    #获取锁,用于线程同步
    lock.acquire()
    for i in range(1000000):
        num=num+n
        num=num-n
    #释放锁,开启下一个线程
    lock.release()
#初始化三个线程,传递不同的参数
t1=threading.Thread(target=task_threading,args=(6,))
t2=threading.Thread(target=task_threading,args=(17,))
t3=threading.Thread(target=task_threading,args=(11,))

#start()方法开启三个线程
t1.start()
t2.start()
t3.start()
#等待运行结束,join()方法阻塞主线程,等待当前线程运行结束
t1.join()
t2.join()
t3.join()
print(num)
复制代码

 多线程同步之Semaphore(信号量) 互斥锁是只允许一个线程访问共享数据,而信号量是同时允许一定数量的线程访问共享数据,比如银行柜台有五个窗口,允许同时有5个人办理业务,后面的只能等待,待柜台有人办理完业务后才可以进入相应的柜台办理,示例如下,使用信号量控制并发:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time
import threading
 
#同时只有5个人办理业务
#threading.BoundedSemaphore(value) values是一个内部计数,values默认是1,如果小于0,则会抛出 ValueError 异常,可以用于控制线程数并发数
semaphore=threading.BoundedSemaphore(5)
#模拟银行办理业务
def yewubanli(name):
    semaphore.acquire()
    time.sleep(3)
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} {name}正在办理业务")
    semaphore.release()
 
thread_list=[]
for i in range(12):
    t=threading.Thread(target=yewubanli,args=(i,))
    thread_list.append(t)
 
for thread in thread_list:
    thread.start()
 
for thread in thread_list:
    thread.join()

 

posted @   小白成长记-yan  阅读(2459)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示