python 多线程操作

  • 一、概念
  • 1.什么是线程?
  • 2.为什么使用多线程
  • 3.线程的优点:
  • 二、Python中使用线程有两种方式:函数或者用类来包装线程对象。
  • 1.函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下:
  • 2.使用 threading 模块创建线程
  • 三、线程相关作业


一、概念

1.什么是线程?

线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。
线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行

2.为什么使用多线程

线程在程序中是独立的、并发的执行流。与分隔的进程相比,进程中线程之间的隔离程度要小,它们共享内存、文件句柄
和其他进程应有的状态。因为线程的划分尺度小于进程,使得多线程程序的并发性高。进程在执行过程之中拥有独立的内存单元,而多个线程共享内存,从而极大的提升了程序的运行效率。
线程比进程具有更高的性能,这是由于同一个进程中的线程都有共性,多个线程共享一个进程的虚拟空间。线程的共享环境包括进程代码段、进程的共有数据等,利用这些共享的数据,线程之间很容易实现通信。
操作系统在创建进程时,必须为改进程分配独立的内存空间,并分配大量的相关资源,但创建线程则简单得多。因此,使用多线程来实现并发比使用多进程的性能高得要多。

3.线程的优点:

①进程之间不能共享内存,但线程之间共享内存非常容易。
② 操作系统在创建进程时,需要为该进程重新分配系统资源,但创建线程的代价则小得多。因此使用多线程来实现多任务并发执行比使用多进程的效率高
③python语言内置了多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了python的多线程编程。

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

1.函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下:

_thread.start_new_thread ( function, args(, kwargs) )

参数说明:
function - 线程函数。
args - 传递给线程函数的参数,他必须是个tuple类型。
kwargs - 可选参数。

import _thread
import time

def thread_1():
    while(1):
        print("hello")
        time.sleep(1)
    return

def thread_2():
    while(1):
        print("world")
        time.sleep(1)
    return

def main():
    try:
        _thread.start_new_thread(thread_1,())
        _thread.start_new_thread(thread_2,())

    except Exception as e:       
 	    print("线程创建失败---异常---:", e)            
    while 1:                     
   	    pass   
main()

2.使用 threading 模块创建线程

Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。

_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。

threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:

threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。

我们可以通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法:

class MyThread(threading.Thread):
    def __init__(self,n):
        super(MyThread,self).__init__()   #重构run函数必须写
        self.n = n

    def run(self):
        print('task',self.n)
        time.sleep(1)
        print('2s')
        time.sleep(1)
        print('1s')
        time.sleep(1)
        print('0s')
        time.sleep(1)

if __name__ == '__main__':
    t1 = MyThread('t1')
    t2 = MyThread('t2')
    t1.start()
    t2.start()

三、线程相关作业

有四个线程,每个线程只打印一个字符,这四个字符分别是 a b c d ,现在要求你做到四个线程顺序打印 a b c d ,且每个线程都打印10次

实现代码:

flag = 0
def th1():
    i=0
    global flag
    while(i<10):
        if(flag == 0):
            print("a")
            i += 1
            flag = 1
        time.sleep(1)
def th2():
    i=0
    global flag
    while(i<10):
        if(flag == 1):
            print("b")
            i += 1
            flag = 2
        time.sleep(1)

def th3():
    i=0
    global flag
    while(i<10):
        if(flag == 2):
            print("c")
            i += 1
            flag = 3
        time.sleep(1)

def th4():
    i=0
    global flag
    while(i<10):
        if(flag == 3):
            print("d")
            i += 1
            flag = 0
        time.sleep(1)
def main():
    try:
       _thread.start_new_thread(th1,(),) 
       _thread.start_new_thread(th2,(),) 
       _thread.start_new_thread(th3,(),) 
       _thread.start_new_thread(th4,(),) 
    except Exception as e:
        print("异常",e)
    while(1):
        pass
main()