zoukankan      html  css  js  c++  java
  • Python3使用线程

    Python2标准库中提供了两个模块thread和threading支持多线程。
    thread有一些缺陷在Python3中弃用,为了兼容性,python3 将 thread 重命名为 "_thread",在Python3中推荐直接使用threading。

    创建线程对象

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

    参数说明:

    group 应该为 None;为了日后扩展 ThreadGroup 类实现而保留。
    target 是用于 run() 方法调用的可调用对象。默认是 None,表示不需要调用任何方法。
    name 是线程名称。默认情况下,由 "Thread-N" 格式构成一个唯一的名称,其中 N 是小的十进制数。
    args 是用于调用目标函数的参数元组。默认是 ()。
    kwargs 是用于调用目标函数的关键字参数字典。默认是 {}。
    如果 daemon 不是 None,线程将被显式的设置为 守护模式,不管该线程是否是守护模式。如果是 None (默认值),线程将继承当前线程的守护模式属性。

    线程对象其中的几个方法

    start()开始线程活动。
    run() 代表线程活动的方法。
    join(timeout=None) 等待,直到线程终结
    setDaemon()设置是否为守护线程

    一、使用线程有两种方式:函数或者用类来包装线程对象

    例子1:使用函数

    import random
    import threading 
    import time
    
    def run(threadName):
        for i in range(5):
            time.sleep(random.random())
            #这里只是演示参数,获取当前线程名可用threading.currentThread().getName()
            print('{} : {}'.format(threadName, i))
    
    t1 = threading.Thread(target=run, args=('thread 1',))
    t1.start()
    t2 = threading.Thread(target=run, args=('thread 2',))
    t2.start()
    
    '''
    运行结果:
    thread 2 : 0
    thread 2 : 1
    thread 1 : 0
    thread 1 : 1
    thread 2 : 2
    thread 2 : 3
    thread 1 : 2
    thread 1 : 3
    thread 2 : 4
    thread 1 : 4
    '''

    例子2:使用类(运行结果和例子1类似)

    import random
    import threading 
    import time
    
    class test(threading.Thread):
        def __init__(self,name):
            super().__init__()
            self.name = name
        def run(self):
            for i in range(5):
                time.sleep(random.random())
                print('{} : {}'.format(self.name, i))
            
    t1 = test('thread 1')
    t1.start()
    t2 = test('thread 2')
    t2.start()

    二、join(timeout=None) 方法

    一个进程启动之后,会默认产生一个主线程A,当创建子线程B后,如果不调用B.join(),则主线程A和子线程B会同时执行;
    如果调用B.join()则主线程会在调用处等待子线程B执行完后,才继续往下执行。
    参数timeout是可选的,代表线程运行的最大时间,如果超过这个时间,不管这个线程有没有执行完毕都会被回收,然后主线程会接着执行。
    join在start后才调用。

    1、不调用子线程join方法

    import random
    import threading 
    import time
    
    def run():
        name = threading.currentThread().getName()
        print('{} start'.format(name))
        time.sleep(random.random())
        print('{} end'.format(name))
    
    threads = []
    for i in range(5):
        threads.append(threading.Thread(target=run))
    
    for th in threads:
        th.start()
    
    print("finished")
    
    '''
    运行结果
    Thread-1 start
    Thread-2 start
    Thread-3 start
    Thread-4 start
    Thread-5 startfinished
    
    Thread-5 end
    Thread-3 end
    Thread-2 end
    Thread-4 end
    Thread-1 end
    '''

    2、调用子线程join方法

    import random
    import threading 
    import time
    
    def run():
        name = threading.currentThread().getName()
        print('{} start'.format(name))
        time.sleep(random.random())
        print('{} end'.format(name))
    
    threads = []
    for i in range(5):
        threads.append(threading.Thread(target=run))
    
    for th in threads:
        th.start()
    
    #等待,直到线程终结。
    for th in threads:
        th.join()
    
    print("finished")
    
    '''
    运行结果
    Thread-1 start
    Thread-2 start
    Thread-3 start
    Thread-4 start
    Thread-5 start
    Thread-3 end
    Thread-5 end
    Thread-4 end
    Thread-1 end
    Thread-2 end
    finished
    '''

    三、setDaemon()方法

    主线程A中创建子线程B后,如果调用B.setDaemon(),把子线程设置为守护线程。
    表示主线程A一旦执行结束,不管子线程B是否执行完成,会全部被终止。
    setDaemon和join相反,在start之前设置。

    备注:
    主线程在其它非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将会被回收,而进程必须保证非守护线程都运行完毕后才能结束。
    所以如果存在多个子线程,假设有守护线程B,又有非守护线程C,则主线程会等待非守护线程C执行完,守护线程B如果还没执行完则会被终止。

    import threading 
    import time
    
    def run():
        name = threading.currentThread().getName()
        print('{} start'.format(name))
        time.sleep(2)
        #下面这行代码因为主线程已经执行结束,被终止执行
        print('{} end'.format(name))
    
    print("start")
    
    t = threading.Thread(target=run)
    t.setDaemon(True)
    t.start()
    
    time.sleep(1)
    
    print("finished")
    
    '''
    运行结果
    start
    Thread-1 start
    finished
    '''

     四、线程锁

    每个线程互相独立,相互之间没有任何关系,但是在同一个进程中的资源,线程是共享的,如果不进行资源的合理分配,对数据造成破坏,使得线程运行的结果不可预期。这种现象称为“线程不安全”。
    下面例子,如果不用线程锁Lock,则每次得到的结果都不一样。

    from threading import Thread, Lock
    lock = Lock()
    total = 0
    
    #如果不使用lock那么,最后得到的数字不一定为0;
    def cal(type):
        global total    
        for i in range(1000000):
            lock.acquire() 
            if(type == '+'):
                total += 1
            else:
                total -= 1
            lock.release()
        
    thread1 = Thread(target=cal,args=('+',))
    thread2 = Thread(target=cal,args=('-',))
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    
    print(total)
  • 相关阅读:
    LoadRunner脚本转化成Jmeter脚本
    LoadRunner场景运行错误解决方法
    IntelliJ IDEA lombok插件的安装和使用
    js瀑布流加载数据
    js获取浏览器高度和宽度值(多浏览器 图解经典) 转载
    MPMoviePlayerViewController和MPMoviePlayerController
    NSString的内存管理问题
    cocos2D icon
    Singleton 单例模式
    Cocos2d中各种坐标位置关系
  • 原文地址:https://www.cnblogs.com/gdjlc/p/11425406.html
Copyright © 2011-2022 走看看