线程

定义

1.线程:是进程中一个"单一的连续控制流程"/执行路径
2.线程又被称为轻量级进程(lightweight process)
3.Threads run at the sama time,independently of one another
4.一个进程可拥有多个并行的线程(concurrent).
在这里插入图片描述
●进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
●一个程序至少有一个进程,一个进程至少有一个线程
●线程是进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位。
●线程是自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(计数程序,一组寄存器和栈),但是他可与同属一个进程的其他线程共享进程所拥有的全部资源。
●线程的划分尺度小于进程(资源比进程小),使得多线程程序的并发性高
●线程不能独立执行,必须依存在进程中
●线程和进程在使用上各有优缺点:线程执行开销小,但是不利于资源的管理和保护,进程反之

在这里插入图片描述
在一个进程内的所有线程共享全局变量,能够在不适用其他方式的前提下完成多线程之间的数据共享
缺点就是,线程是对全局变量随意遂改可能造成多线程之间全局变量的混乱(线程非安全)

Threading模块常用方法
threading.activeCount(): 返回正在运行的线程数量。
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
len(threading.enumerate)==threading.activeCount结果是True

线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run(): 用以表示线程活动的方法。
start():开启线程。
join([time]): 设置join之后,主线程等待子线程全部执行完成后
或者子线程超时后,主线程才结束。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。

例子:

import threading
from time import sleep,ctime
def sing():
    for i in range(3):
        print("正在唱歌...%d"%i)
        sleep(1)
def dance():
    for i in range(3):
        print("正在跳舞...%d"%i)
        sleep(1)
if __name__ == "__main__":
    print("----开始----%s"%ctime())
    t1=threading.Thread(target=sing)
    t1.start()

    t2=threading.Thread(target=dance)
    t2.start()


    while True:
        #查看进程次数
    length = len(threading.enumerate())
        # length=threading.active_count()
        print("当前运行的线程数为:%d"%length)
        if length <= 1:
            break
        sleep(0.5)

例二:

import threading
from time import time,sleep
def fun(num):
    print("线程执行%d"%num)
    sleep(2)
for i in range(5):
    #简单的线程
    t=threading.Thread(target=fun,args=(i+1,))
    t.start()
print("\n主线程结束")
print(threading.active_count())

例三:

#重写run方法
import threading
import time
class MyThread(threading.Thread):
    def __init__(self,num,str1):
        super().__init__()
        self.num=num
        self.str1=str1
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg="I'm "+self.name+'@'+str(i)+" num :"+str(self.num)+"str1:"+self.str1
            print(msg)
if __name__=="__main__":
    t=MyThread(10,'abc')
    t.start()

例四:

import threading
import time

g_num = 0


def work1(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("----in work1, g_num is %d---" % g_num)


def work2(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("----in work2, g_num is %d---" % g_num)


print("---线程创建之前g_num is %d---" % g_num)

t1 = threading.Thread(target=work1, args=(1000000,))  # 改为1000000
t1.start()

t2 = threading.Thread(target=work2, args=(1000000,))  # 改为1000000
t2.start()

while len(threading.enumerate()) != 1:
    time.sleep(1)

print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)

例五:

#锁
import threading
import time
g_num=0
def work1(num):
    global g_num
    mexFlag=mex.acquire(True)#加锁
    if mexFlag:
        for i in range(num):
            g_num+=1
        mex.release()
    print("work1------%d-------" % g_num)
def work2(num):
    global g_num
    mexFlag = mex.acquire(True)  # 加锁
    if mexFlag:
        for i in range(num):
            g_num+=1
        mex.release()
    print("\nwork2------%d-------"%g_num)

if __name__=="__main__":
    mex=threading.Lock()#互斥锁
    t=threading.Thread(target=work1,args=(1000000,))
    t.start()
    t1=threading.Thread(target=work2,args=(1000000,))
    t1.start()
    while True:
        if len(threading.enumerate()) !=1:
            time.sleep(1)
        else:
            break;
print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)



#
# import threading, multiprocessing
# def loop():
#     x = 0
#     while True:
#                     x = x ^ 1
# for i in range(multiprocessing.cpu_count()*2):
#  t = threading.Thread(target=loop)
#  t.start()
# print(multiprocessing.cpu_count())

一把锁如果忘了解锁会形成死锁,多吧锁也可能形成死锁
在这里插入图片描述
多把锁形成死锁
在这里插入图片描述
使用锁使程序顺序运行

通知锁控制线程的执行顺序
from threading import Thread,Lock
import time
class Thread1(Thread):
    def run(self):
        while True:
            if lock1.acquire():
                print("lock1------")
                time.sleep(2)
                lock2.release()
class Thread2(Thread):
    def run(self):
        while True:
            if lock2.acquire():
                print("lock2------")
                time.sleep(2)
                lock3.release()
class Thread3(Thread):
    def run(self):
        while True:
            if lock3.acquire():
                print("lock3------")
                time.sleep(2)
                lock1.release()
if __name__=="__main__":
        #使用Lock()创建互斥锁
        lock1=Lock()
        lock2=Lock()
        # 锁上
        lock2.acquire()
        lock3=Lock()
        # 锁上
        lock3.acquire()
        t1=Thread1()
        t2=Thread2()
        t3=Thread3()
        t1.start()
        t2.start()
        t3.start()

     #不加锁的情况
# #通知锁控制线程的执行顺序
# from threading import Thread,Lock
# import time
# class Thread1(Thread):
#     def run(self):
#         while True:
#
#                 print("lock1------")
#                 time.sleep(1)
#
# class Thread2(Thread):
#     def run(self):
#         while True:
#
#             print("lock2------")
#             time.sleep(1)
#
# class Thread3(Thread):
#     def run(self):
#         while True:
#
#                 print("lock3------")
#                 time.sleep(1)
#
# if __name__=="__main__":
#
#     t1=Thread1()
#     t2=Thread2()
#     t3=Thread3()
#     t1.start()
#     t2.start()
#     t3.start()

如何去在线程的执行过程中销毁对象

import time
import threading

class DownThread:
    def __init__(self):
        self._running = True
    def terminate(self):
        self._running = False

    def run(self, n):
        while self._running and n > 0:
            print('T-minus', n)
            n -= 1
            time.sleep(1)

if __name__ == '__main__':
    c = DownThread()
    t = threading.Thread(target=c.run, args=(10,))
    t.start()
    time.sleep(3)
    c.terminate()
    t.join()

ThreadLocal变量
在这里插入图片描述

#ThreadLocal变量
import threading
#创建全局ThreadLocal对象
local_school=threading.local()
def process_student():
    #获取当前关联的student:
    std=local_school.student
    print("Hello,%s(in %s)"%(std,threading.currentThread().name))
def process_thread(name):
    #绑定上面函数的student
    local_school.student=name
    process_student()
t1=threading.Thread(target=process_thread,args=("zhangsan",),name="t1")
t2 =threading.Thread(target=process_thread,args=("老王",),name="t2")
t1.start()
t2.start()
t1.join()
t2.join()


 线程池

# 一个线程的运行时间可以分为3部分:线程的启动时间、线程体的运行时间和线程的销毁时间。
# 在多线程处理的情景中,如果线程不能被重用,就意味着每次创建都需要经过启动、销毁和运行3个过程。
# 这必然会增加系统相应的时间,降低了效率。


# 使用线程池:由于线程预先被创建并放入线程池中,同时处理完当前任务之后并不销毁而是被安排处理下一个任务,
# 因此能够避免多次创建线程,从而节省线程创建和销毁的开销,能带来更好的性能和系统稳定性。


# 线程池基本原理: 我们把任务放进队列中去,然后开N个线程,每个线程都去队列中取一个任务,
# 执行完了之后告诉系统说我执行完了,然后接着去队列中取下一个任务,直至队列中所有任务取空,退出线程。


import threading
from threading import Thread
import time
from queue import Queue


# 创建队列实例, 用于存储任务
queue = Queue()




# 定义需要线程池执行的任务
def do_job():
    while True:
        i = queue.get()
        time.sleep(1)
        print('index %s, curent: %s' % (i, threading.current_thread()))
        queue.task_done()




if __name__ == '__main__':
    # 创建包括3个线程的线程池
    for i in range(3):
        t = Thread(target=do_job)
        t.start()


    # 模拟创建线程池3秒后塞进10个任务到队列
    time.sleep(3)
    for i in range(10):
        queue.put(i)


    queue.join()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值