首页 > 编程语言 >py02-python之线程

py02-python之线程

时间:2023-11-28 17:48:48浏览次数:27  
标签:Thread thread python threading 线程 py02 print target

1、线程:

(1)讲程是分配资源的最小单位,一旦创建一个进程就会分配一定的资源,就像两个人聊OQ就需要打开两个QQ软件一样,是比较浪费资源的。
线程是程序执行的最小单位,实际上进程只负责分配资源,而利用这些资源执行程序的是线程,也就说进程是线程的容器,一个进程中最少有一个线程来负责执行程序,同时线程自己不拥有系统资源,只需要一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源.这就像通过一个QQ软件(一个进程)打开两个窗口(两个线程)跟两个人聊天一样,实现多任务的同时也节省了资源。

(2)线程的创建步骤

# 1.导入线程模块
import threading
# 2.通过线程类创建线程对象
线程对象 = threading.Thread(target=任务名)
# 3.启动线程执行任务
线程对象.start()

(3)通过线程类创建线程对象:线程对象 = threading.Thread(target=任务名)
参数说明:
target:执行的目标任务名,这里指的是函数名(方法名)
name:线程名,一般不用设置
group:线程组,目前只能使用None

(4)线程创建与启动的代码

# 创建子线程
sing_thread= threading.Thread(target=sing)
# 创建子线程
dance_thread = threading.Thread(target=dance)
# 启动线程
sing_thread.start()
dance_thread.start()

(5)线程执行带有参数的任务:args-以元组的方式给执行任务传参、kwargs-以字典方式给执行任务传参

# target: 线程执行的函数名
# args: 表示以元组的方式给函数传参
sing_thread = threading.Thread(target=sing, args=(3,))
sing_thread.start()
# target: 线程执行的函数名
# kwargs:表示以字典的方式给函数传参
dance_thread = threading.Thread(target=dance,kwargg={"count": 3})
#开启线程
dance thread.start()

(6)主线程和子线程的结束顺序
对比进程,主线程会等待所有的子线程执行结束后主线程再结束

(7)设置守护主线程:要想主线程不等待子线程执行完成可以设置守护主线程

#设置守护主线程方式1,daemon=True 守护主线程
work_thread= threading.Thread(target=work, daemon=True)
#设置守护主线程方式2
# work_thread.setDaemon(True)
work_thread.start()
#主线程延时1秒
time.sleep(1)
print ("over")

(8)获取当前的线程信息:

#通过current_thread方法获取线程对象
current_thread = threading.current_thread()
#通过current_thread对象可以知道线程的相关信息,例如被创建的顺序
print(current_thread)

9)线程间的执行顺序:线程之间执行是无序的,是由CPU调度决定某个线程先执行的

2、进程和线程对比:

(1)线程是依附在进程里面的,没有进程就没有线程
(2)一个进程默认提供一条线程,进程可以创建多个线程
(3)创建进程的资源开销要比创建线程的资源开销要大
(4)进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
(5)线程不能够独立执行,必须依存在进程中
(6)进程优缺点:可以用多核,但资源开销大
(7)线程优缺点:资源开销小,但不能使用多核

3、join方法,等待子线程结束

import threading
import time


def my_print(n):
    for i in range(n):
        print(i)
        time.sleep(0.5)


t_lst = []
for i in range(3):
    t = threading.Thread(target=my_print,args=(5,))
    t_lst.append(t)

for t in t_lst:
    t.start()

for t in t_lst:
    t.join()

print('主线程')

4、threading.local:线程隔离,比如使全局变量在线程中隔离,当做局部变量使用,互不影响

(1)例子1

import threading

mylocal = threading.local()
mylocal.value = 0


def add_one(index):
    mylocal.value = index
    print(mylocal.value)

for i in range(1, 11):
    t = threading.Thread(target=add_one,args=(i,))
    t.start()
print(mylocal.value)

(2)例子2

import threading
import time


# 利用local类,创建一个全局对象 local_obj
local_obj = threading.local()


def func():
    local_obj.var = 0
    # 如果使用局部变量,函数调用需要传参
    func_print()

def func_print():
    for k in range(100):
        time.sleep(0.01)
        # 直接使用local_obj.var,自动获取当前线程对应的属性值
        local_obj.var += 1
    print(f'线程id:{threading.get_ident()},thread-local数据:{local_obj.var}')

# 创建3个线程,并启动
for th in range(3):
    threading.Thread(target=func,).start()
print(mylocal.value)

5、获取线程id:threading.get_ident()

6、threading.Lock():线程加锁,加锁后必须释放后再加锁,不然会死锁

(1)操作:

m_lock = threading.Lock()
m_lock.acquire()    # 加锁
m_lock.release()   # 释放锁

(2)例子

import threading
import time

m_lock = threading.Lock()

a = 0
def worker():
    time.sleep(1)
    global a
    for i in range(100000):
        m_lock.acquire()    # 加锁
        a += 1
        m_lock.release()    # 释放锁
# 或者直接:with m_lock,不用加锁和释放锁,简化为这一步
thread_lst = []
for i in range(5):
    t = threading.Thread(target=worker)
    thread_lst.append(t)

for t in thread_lst:
    t.start()

for t in thread_lst:
    t.join()

print(a)

7、threading.RLock():线程加锁,可以连续加锁,几次加锁几次释放就行,不会死锁,安全

8、多线程线程同步---Condition,Condition被称为条件变量,提供以下方法

(1)acquire-加锁
(2)release-释放锁
(3)wait-调用wait方法后,waitting池会记录这个线程,同时,这个线程也进入到了阻塞状态,直到超时或者别的线程唤醒它
(4)notify-唤醒处于waiting状态的线程,被唤醒的这个线程会再次acquire锁,得到锁以后继续执行

import threading
import time

condition = threading.Condition()
products = 12


class Producer(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        global condition, products
        while True:
            if condition.acquire():
                if products < 10:
                    products += 1;
                    print("Producer(%s):deliver one, now products:%s" %(self.name, products))
                    condition.notify()

                else:
                    print("Producer(%s):already 10, stop deliver, now products:%s" %(self.name, products))
                    condition.wait();
                condition.release()
                time.sleep(2)

class Consumer(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        global condition, products
        while True:
            if condition.acquire():
                if products > 1:
                    products -= 1
                    print("Consumer(%s):consume one, now products:%s" %(self.name, products))
                    condition.notify()
                else:
                    print("Consumer(%s):only 1, stop consume, products:%s" %(self.name, products))
                    condition.wait()
                condition.release()
                time.sleep(2)

if __name__ == "__main__":
    for p in range(0, 2):
        p = Producer()
        p.start()

    for c in range(0, 10):
        c = Consumer()
        c.start()

9、python多线程同步-信号量-Semaphore:内部维护了一个计数器,每一次acquire操作都会让计数器减1,每一次release操作都会让计数器加1,当计数器为0时,任何线程的acquire操作都不会成功,Semaphore确保对资源的访问有一个上限,控制并发量

import threading
import time
semaphore = threading.Semaphore(2)


def worker(id):
    print('thread {id} acquire semaphore'.format(id=id))
    semaphore.acquire()
    print('thread {id} get semaphore do something'.format(id=id))
    time.sleep(2)
    semaphore.release()
    print('thread {id} release semaphore'.format(id=id))


for i in range(10):
    t = threading.Thread(target=worker, args=(i, ))
    t.start()

10、python多线程同步-事件Event:

(1)事件Event:灵活的协调线程间的操作,提供了下面几个方法:
(1-1)set():将事件内部标识设置为True,Event对象最初创建时,内部标识默认是False
(1-2)wait():当在线程中调用wait时,如果事件内部标识为False,则会阻塞,直到set方法被调用,将内部标识设置为True
(1-3)clear():将内部标识重新设置为False
(1-4)is_set():如果内部标识是True,则返回True,反之,返回False

。。。未完待续

标签:Thread,thread,python,threading,线程,py02,print,target
From: https://www.cnblogs.com/wangfengzi/p/17862521.html

相关文章

  • Python-JSON文件操作简化的工具库,支持读取和修改
    这是一个关于python操控json的工具类可以利用get方法以路径的形式查看内容,输出的格式为列表或字典change方法用于修改指定路径下的内容,支持修改内容为字典和列表的形式修改后使用save方法进行保存以下是代码:importjsonimporttimeimportrandomclassError_message:......
  • Java多线程转账
    Java多线程转账关键词:多线程,Java以前的一道面试题,要求是使用Java多线程,实现一个转账业务。不考虑数据库,不考虑其他第三方系统。只考虑当前Java程序内各个账户进行转账,保证转账金额正确性和转账功能效率。想起那大约还是两年前,是线上面试,面试官给完题目就关闭视频通话,让我自己去......
  • py01-python之进程
    一、进程1、概念(1)并发:在一段时间内交替去执行多个任务。例如对于单核cpu处理多任务,操作系统轮流让各个任务交替执行(任务数量大于CPU的核心数)。(2)并行:在一段时间内真正的同时一起执行多个任务。例如对于多核cpu处理多任务,操作系统会给cpu的每个内核安排一个执行的任务,多个内......
  • python保留小数点后几位的方法
    一、保留小数点后n位方法一:使用字符串格式化注意:使用字符串格式化后的是字符串格式a=12.3456print("%.3f"%a)#保留小数点后三位print("%.2f"%a)#保留小数点后两位输出12.34612.35方法二:使用round内置函数注意:使用round后的是浮点数格式a=12.3456a1=round(a......
  • Python常用的数据处理函数和模块
    Python还提供了许多其他用于数据处理和转换的内置函数和模块。以下是一些常用的数据处理函数和模块:sortedsorted(iterable,key=func,reverse=False)用于对可迭代对象进行排序。你可以指定一个可选的key函数来自定义排序规则,以及一个可选的reverse参数来控制升序或降序排......
  • python中列表(list)拼接的三种方法
    你可以使用Python中的列表拼接操作来合并两个或多个列表。Python提供了几种方式来实现列表的拼接,包括使用+运算符、extend()方法和列表解析。以下是这些方法的示例:1.使用+运算符:list1=[1,2,3]list2=[4,5,6]concatenated_list=list1+list2print(concate......
  • python 入门
    type(183)显示的是183的数据类型intprint("183")显示183print(183,172)显示183172age=10name=strehdprint("%d %s"%(age,name))显示的是10strehd还有一张传参形式print(f"  {name}11{age}")显示的是strehd11109//2=49%2=19**2=81%m.nd比如%7.2d,限制了数字的宽度和精度......
  • 使用Python中的tarfile :解决Mac和Linux 打包冲突问题
    Python对tar包的操作目的:兼容linux和macOS系统上都能正常打包和解包起初:在macOS上使用命令tar打得包在linux上根本无法解开。原因:https://blog.csdn.net/qq_44214671/article/details/127804905解决办法:python是兼容MacOS和Linux,直接用Python的tarfile操作tar包。https://do......
  • python脚本中调用django环境
    #在脚本中调用djagno服务importosif__name__=='__main__':#1引入django配置文件os.environ.setdefault('DJANGO_SETTINGS_MODULE','day67.settings')#2让djagno启动importdjangodjango.setup()#3使用表模型fromapp01impor......
  • python用户交互
    用户交互:就是在计算机中input/输入数据,计算机print/输出结果如何与用户交互:输入input,输出:print ......