ITPub博客

首页 > 应用开发 > Python > 线程

线程

原创 Python 作者:Winter 时间:2019-04-22 18:22:22 0 删除 编辑

1.什么是线程

  • 线程,有时被称为轻量进程,是程序执行流的最小单元;

  • 进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础;

2.如何定义线程

  • 在Python中,使用threading库来创建线程;

  • 创建进程的语法


threading.Thread(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None);

  • group :为线程组,但是Python中没有线程组,所以这是保留参数;

  • target :为可调用对象,也就是任务, 可以是函数,如果是实例,那么实例的类必须实现 __call__ 方法;

  • name :指定线程的名称;

  • args、kwargs :给线程任务传递参数、关键字参数;

  • daemon :指定子线程是否需要主线程等待,主线程是non-daemon线程;

3.如何使用线程


# 示例1:
import threading
def worker():
    print('I am worker')
thead_obj = threading.Thread(target=worker, name='worker')
thead_obj.start()

  • Python中的线程没有优先级、线程组、停止、挂起、销毁、恢复的概念;

  • 线程退出的方式有两种:线程任务执行完毕、或线程内部抛出异常;


# 示例1:死循环,会一直执行
import threading
import time
def worker():
    while True:
        time.sleep(1)
        print('我在工作')
    else:
        print('执行完毕')
thread_obj = threading.Thread(target=worker, name='worker')
thread_obj.start()
# 示例3:条件不满足时,程序会执行完毕
import threading
import time
def worker():
    number = 10
    while number:
        time.sleep(1)
        print('我在工作')
        number -= 1
    else:
        print('执行完毕')
thread_obj = threading.Thread(target=worker, name='worker')
thread_obj.start()
# 示例4:参数传递
import threading
import time
def worker(num):
    number = num
    while number:
        time.sleep(1)
        print('我在工作')
        number -= 1
    else:
        print('执行完毕')
thread_obj = threading.Thread(target=worker, name='worker', args=(3,))
thread_obj.start()

  • threading.active_count() :依然存活的线程数,包括主线程;

  • threading.current_thread() :返回当前线程实例对象;

  • threading.enumerate() :返回当前存活的线程对象列表,包括主线程,但是不包括终止线程和未启动线程;

  • threading.main_thread() :返回主线程实例对象;

  • threading.get_ident() : 返回当前线程的ID;


# 实例5:线程的threading模块的相关函数
import threading
import time
def showInfo():
    print('active_thread_count = {}'.format(threading.active_count()))
    print('current_thread = {}'.format(threading.current_thread()))
    print('enumerate = {}'.format(threading.enumerate()))
    print('main_thread = {}'.format(threading.main_thread()))
    print('get_ident = {}'.format(threading.get_ident()))
def worker(num):
    number = num
    while number:
        time.sleep(1)
        print('我在工作')
        number -= 1
    else:
        print('执行完毕')
if __name__ == '__main__':
    thread_obj = threading.Thread(target=worker, name='worker', args=(5, ))
    thread_obj.start()
    showInfo()

  • thread_obj.name :属性装饰器实现,获取线程名称;

  • thread_obj.name = 'thread name' : 设置线程名称;

  • thread_obj.ident :线程id;

  • thread_obj.is_alive() :显示线程是否存活,返回Bool值;


# 示例6:线程实例对象的方法
import threading
import time
def worker(num):
    number = num
    while number:
        time.sleep(1)
        print('我在工作')
        number -= 1
    else:
        print('执行完毕')
if __name__ == '__main__':
    thread_obj = threading.Thread(target=worker, name='worker', args=(5, ))
    thread_obj.start()
    print(thread_obj.name)
    thread_obj.name = 'new worker'
    print(thread_obj.name)
    print(thread_obj.ident)
    print(thread_obj.is_alive())

4.线程start方法和run方法的区别


import threading
import time
def worker(num):
    number = num
    while number:
        time.sleep(1)
        print('我在工作')
        number -= 1
    else:
        print('执行完毕')
if __name__ == '__main__':
    thread_obj = threading.Thread(target=worker, name='worker', args=(5, ))
    thread_obj.start()
    # thread_obj.run()
    print(thread_obj.name)
    thread_obj.name = 'new worker'
    print(thread_obj.name)
    print(thread_obj.ident)
    print(thread_obj.is_alive())

  • start 方法会在内存中,启动一个新的线程运行任务;

  • run 方法不会启动新的线程,只是在主线程中执行任务;

5.什么是线程安全

  • 一般在使用多线程的时候,如果需要打印线程的信息,不会使用print函数打印,而是使用logging日志模块打印,因为考虑到print函数在打印过程中 可能出现线程的切换;

6.如何确保线程安

  • 使用logging模块,把线程的信息通过日志的形式打印出来;

7.daemon线程和非daemon线程


import threading
import time
def worker(num):
    number = num
    while number:
        time.sleep(1)
        print('{}在工作'.format(threading.current_thread().name))
        number -= 1
    else:
        print('执行完毕')
if __name__ == '__main__':
    thread_obj = threading.Thread(target=worker, name='worker', args=(5, ), daemon=False)
    # thread_obj = threading.Thread(target=worker, name='worker', args=(5,), daemon=True)
    thread_obj.start()
    time.sleep(3)
    print('主线程执行完毕')

  • 线程中有父子的概念,如果在主线程中启动了一个线程,那么主线程就是父线程,启动的这个工作线程就是子线程;

  • 主线程是 non-daemon线程 ,也就是 daemon=False , 如果子线程的 daemon=False ,那么主线程会等待子线程执行完毕,主线程才会终止,如果 为True, 那么主线程将不会等待子线程,而是主线程执行完毕后,子线程就会终止运行;

  • daemon选项必须在启动线程之前设定;

8.线程实例的join方法


import threading
import time
def worker(num):
    number = num
    while number:
        time.sleep(1)
        print('{}在工作'.format(threading.current_thread().name))
        number -= 1
    else:
        print('执行完毕')
if __name__ == '__main__':
    #
    thread_obj = threading.Thread(target=worker, name='worker', args=(5,), daemon=True)
    thread_obj.start()
    thread_obj.join()  # 主线程在此处开始阻塞
    print('主线程执行完毕')

  • 在当前线程中调用另一个线程的join方法,当前线程会在此处被阻塞,直到被调用的线程结束运行或终止,timeout指定被阻塞的时长,如果没有指定 ,那么就一直阻塞直到调用线程终止;

9.timer定时器


threading.Timer(self, interval, function, args=None, kwargs=None)可以创建一个定时任务
import threading
from threading import Timer
def worker():
    print('I am worker !')
# 等3秒后只需
timer = Timer(interval=3, function=worker, )
# 给定时器取名
timer.setName('worker timer')
timer.start()
print(threading.enumerate())

  • Timer是Thread的一个派生类,用于在指定时间后调用一个方法,如果想实现每隔一段时间就调用一个函数的话,就要在Timer调用的函数中,再次 设置Timer;

参考: https://www.9xkd.com/user/plan-view.html?id=4246838014

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69908432/viewspace-2642191/,如需转载,请注明出处,否则将追究法律责任。

下一篇: 线程同步与并发
请登录后发表评论 登录
全部评论
努力学习,做最好的自己!

注册时间:2019-01-23

  • 博文量
    60
  • 访问量
    43960