• Python多线程笔记(一)


    Python中使用threading模块来实现多线程

    threading提供一些常用的方法

    threading.currentThread()   返回当前的线程变量
    threading.enumerate()      返回一个正在运行的线程的list
    threading.activeCount()    返回正在运行的线程数量,与len(threading.enumerate())  有相同的结果。
    threading.TIMEOUT_MAX   设置threading全局超时时间。

    threading模块提供Thread类的各种同步原语,用于编写多线程程序

    Thread对象

    Thread 类用于表示单独的控制线程,使用下面的函数可以创造一个新线程

     Thread(group=None, target=None, name=None, arg=(), kwarg={}) 

    此函数创造一个新的Thread实例。

    group  值是None,为以后扩展而保留

    target 是一个可调用对象,线程启动时 run()方法将调用此对象,他的默认值是None,表示不调用任何内容

    name   是线程名称,默认创建一个"Thread-N"格式的唯一名称

    args   是传递给target函数的参数元组

    kwargs 是传递给target的关键字参数的字典

    Thread实例t支持一下方法和属性

    t.start()
    通过在一个单独的控制线程中调用run()方法,启动线程。此方法只能用调用一次

    t.run()
    线程启动时将调用此方法。默认情况下,他将调用传递到构造函数中的目标函数。还可以在Thread的子类中重新定义此方法

    t.join()
    等待直到线程终止或者出现超时为止。timeout是一个浮点数,用于指定以秒为单位的超时时间
    线程不能连接自身,而且在线程启动之前就连接它将出现错误。

    t.is_alive()
    如果线程是活动的,返回True,否则返回False。从start()方法返回的那一刻开始,线程就是活动的,知道它的run()方法终止。
    t.isAlive()是老式代码中此方法的别名

    t.name
    线程名称。这个字符串用于唯一识别,可以根据需要将他改为更有意义的值,在老式代码中,t.getName()和t.setName(name)
    函数用于操作线程名称

    t.ident
    整数线程标识符。如果线程尚未启动,值为None

    t.daemon
    线程的布尔型后台标志。必须在调用start()方法之前设置这个标志,它的初始值从创造线程的后台状态继承而来。。当不存在任何活动
    的非后台线程时,整个Python程序将退出。所有程序都有一个主线程,代表初始的控制线程,他不是后台线程。在老式代码中
    t.setDaemon(flag)和t.isDaemon() 函数用于操作这个值

    threading实现多线程有两种方法

    1. 以线程的形式创建和启动一个函数

     1 import threading
     2 import time
     3 
     4 
     5 def clock(interval):
     6     while True:
     7         print("The time is %s" % time.ctime())
     8         time.sleep(interval)
     9 
    10 
    11 t = threading.Thread(target=clock, name='clock', args=(3,))
    12 t.start()

    2. 将同一个线程定义为一个类, 并重写run()方法

     1 import threading
     2 import time
     3 
     4 
     5 class ClockThread(threading.Thread):
     6     def __init__(self, interval):
     7         threading.Thread.__init__(self)
     8         self.interval = interval
     9 
    10     def run(self):
    11         while True:
    12             print("The time is %s" % time.ctime())
    13             time.sleep(self.interval)
    14 
    15 
    16 t = ClockThread(2)
    17 t.start()

    如果将线程定义为类,并且定义自己的__init__()方法,必须想上面这个调用基类构造函数Thread.__init__()。

    如果忘记这一点,将导致严重错误。除run()方法之外,改写线程已经定义的其他方法也会出现错误

    demon=True,线程在后台运行。主程序结束后后台线程无论是否执行完成都将被销毁

     1 import threading
     2 import time
     3 
     4 
     5 def action(arg):
     6     time.sleep(3)
     7     print(arg)
     8 
     9 
    10 for i in range(1, 4):
    11     t = threading.Thread(target=action, args=(i,))
    12     t.daemon = True  # 设置线程为后台线程
    13     t.start()
    14 
    15 
    16 print('thread end!')
    17 time.sleep(1)

    执行结果为:thread end! 

    程序在执行完print('thread end!')后暂停一秒才会退出解释器,而后台线程需要三秒后才能打印出数据。
    daemon=True时后台线程还未来得及完成运行,就因为主程序的退出而被销毁。

    join() 主程序等待所有线程执行完毕后再退出

     1 import threading
     2 import time
     3 
     4 start_time = time.time()
     5 
     6 
     7 def action(arg):
     8     time.sleep(3)
     9     print(arg)
    10 
    11 
    12 for i in range(1, 4):
    13     t = threading.Thread(target=action, args=(i,))
    14     t.daemon = True  # 设置线程为后台线程
    15     t.start()
    16     t.join()
    17 
    18 
    19 print('thread end!')
    20 time.sleep(5)
    21 stop_time = time.time()
    22 print(stop_time-start_time)

    运行结果为:

    1
    2
    3
    thread end!
    14.007635116577148

    从运行结果和运行时间来看,此时程序只能顺序执行,每个线程都被上一个线程的join阻塞,失去了多线程的意义.不加join()时运行时间仅为5.0011246秒

    join()设置超时时间,当线程运行时间超过timeout时间时运行下一步

    import threading
    import time
    
    
    def test1():
        print('start 1: ' + time.strftime('%H:%M:%S') + "
    ")
        time.sleep(6)
        print('stop 1: ' + time.strftime('%H:%M:%S') + "
    ")
    
    
    def test2():
        print('start 2: ' + time.strftime('%H:%M:%S') + "
    ")
        time.sleep(1)
        print('stop 2: ', time.strftime('%H:%M:%S') + "
    ")
    
    
    threads = []
    t1 = threading.Thread(target=test1)
    t1.start()
    threads.append(t1)
    
    t2 = threading.Thread(target=test2)
    t2.start()
    threads.append(t2)
    
    print('start join: ' + time.strftime('%H:%M:%S') + "
    ")
    for tt in threads:
        tt.join(2)
    print('end join: ' + time.strftime('%H:%M:%S') + "
    ")

    当test1运行时超过了timeout时间2秒,就开始运行test2和print()

    Timer对象

    Timer对象用于在稍后的某个时间执行一个函数

     Timer(interval, func[,args [,kwargs]]) 

    创建定时器对象,在过去interval秒时间之后运行函数func.args和kwargs提供传递给func的参数和关键字参数.在调用start()方法后才会启动定时器

    Timer对象t具有以下方法

    t.start()      启动定时器.提供给Timer()方法的函数func将在指定的时间间隔之后执行.
    t.cancel()   如果函数尚未执行,取消定时器

     1 import threading
     2 
     3 
     4 def func():
     5     print('hello world')
     6 
     7 
     8 t = threading.Timer(5, func)
     9 t.start()
    10 t.cancel()  # cancel取消了线程的执行,func不会执行

     

  • 相关阅读:
    自定义控件小结进阶篇
    SQL注入语句 (很全)
    C# winform DataGridView 属性说明 [C# .NET]
    MDI窗体程序中防止子窗体被多次实例化——Singleton的C#实现
    精妙SQL语句大全
    sql语句
    注销时关闭当前窗体,返回登入界面
    C#中DataGridView的使用 [C# .NET]
    C#开发 WinForm中窗体显示和窗体传值相关知识
    HDU2553 (N皇后)
  • 原文地址:https://www.cnblogs.com/niuu/p/10114961.html
Copyright © 2020-2023  润新知