python之线程

概念

线程是多任务编程方式之一,可以使用计算机的多核资源。

线程又称为轻量级的进程,在并发执行上和进程相同。但是一个进程中可以包含多个线程,这些线程共享线程的运行环境。

线程和进程的比较:

1 进程的创建开销大,而线程的创建开销小。

2 进程间的资源共享,只能通过进程间通信。而同一进程下线程间的资源共享,就像使用全局变量一样。

3 多个功能独立的程序需要成为不同的进程。而不能通过多线程凑成一个进程。

4 进程空间独立性高,安全性也高,也较少使用同步和互斥方法。而多个线程间因为数据共享,所以同步和互斥几乎是数据必须必须的。

5 线程也有自己的独立资源,比如说ID,资源集。

创建线程

import threading

t = threading.Thread(target, args, kwargs, name)

t.name 线程名字

t.setName() :设置线程名称

t.getName() : 获取名称

t.join(n) :主线程阻塞等待分支线程退出,n为超时时间

t.start() :启动线程

t.Daemon : daemon属性

如果在进程中创建了多个线程,当主进程结束时,会根据子进程的daemon属性来来处理不同的情况:

1 如果某个子线程的daemon为False,那么主线程结束时会检测这个子线程是否结束,如果子线程没有结束,那么主线程会等待子线程运行完后再退出。

2 如果某个子线程的daemon为True,那么主线程结束时不会对这个子线程进行检查而直接退出,同时daemon为True的子线程将随主线程一起退出,不论它们是否运行完成。

属性Daemon的默认值为False,如果要设置,必须在调用start()方法启用前。

t.is_Daemon() :判断Daemon的状态

t.is_alive() : 判断线程状态

import threading
from time import sleep, ctime

# 听歌
def music(name):
    print('Listen music %s at the %s '%(name, ctime()))
    sleep(2)

# 看书
def read(name):
    print('Read book %s at the %s'%(name, ctime()))
    sleep(5)

if __name__ == '__main__':
    threads = []
    t1 = threading.Thread(target=music, args=('James',))
    threads.append(t1)
    t2 = threading.Thread(target=read, args=('Wade',))
    threads.append(t2)

    # 启动线程
    for t in threads:
        t.start()

    # 回收线程
    for t in threads:
        t.join()

多线程类的创建

import threading
from time import sleep, ctime

exitFlag = 0
class MyThread(threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter

    def run(self):
        print('starting' + self.name)
        print_time(self.name, self.counter, 5)
        print('ending' + self.name)

def print_time(theadName, delay, counter):
    while counter:
        if exitFlag:
            (threading.Thread).exit()
        sleep(delay)
        print("%s at the time:%s"%(theadName, ctime()))
        counter -= 1

if __name__ == '__main__':
    t1 = MyThread(1, 'Mythread-1', 1)
    t2 = MyThread(2, 'Mythread-2', 2)

    t1.start()
    t2.start()

    t1.join()
    t2.join()
    print('主线程退出!!!')
View Code
线程间的通信

线程间的通信一般是使用全局变量,但是这种方法会带来资源的争夺,所有线程间的共享资源一般需要同步互斥机制。

所以为了解决这个问题,我们需要使用2种方法。

方法1: 锁

lock

lock = threading.Lock()

lock.acquire()

lock.release()

import threading

a = b = 0
lock = threading.Lock()

def value():
    while True:
        lock.acquire()
        if a != b:
            print('a = %d, b = %d'%(a, b))
        lock.release()

if __name__ == '__main__':
    t = threading.Thread(target=value)
    t.start()
    while True:
        lock.acquire()
        a += 1
        b += 1
        lock.release()
    t.join()
    '''
    结果是永远也不会发生a!=b,只能在a,b同时修改后读取a,b的值
    '''

方法2:事件 event

python事件主要是主线程控制其他线程的执行,主要提供了wait,set,clear方法。

事件的处理机制:全局定义了一个''Flag'',如果Flag为False,那么当程序执行到event.wait方法就会阻塞,如果Flase为True,那么event.wait方法时将不会阻塞.。

clear:将Flag定义为False。

set:将Flag定义为True。

线程间通信:

使用event可以让以一个线程等待其他线程的通知,

e = threading.Event()

e.set() 设置标志位 设置Flag其为True

e.wait() 等待设置标志位 等待标志变为True后执行,当为False时候阻塞等待

e.clear() 清空标志位 设置Flag其为False

import threading
import random
import time

e = threading.Event()
a = 500

def fun():
    while True:
        time.sleep(2)
        e.wait()
        global a
        print('a = %d'%a)
        a -= random.randint(1, 100)

if __name__ == '__main__':
    t = threading.Thread(target=fun)
    t.start()

    while True:
        time.sleep(1)
        a += random.randint(0, 10)
        if a > 100:
            e.set()
        else:
            e.clear()
    t.join()
    '''
    主线程加数字0-10
    子线程减数字0-100
    当数字大于100时,其Flag一直为True,当小于100时,其Flag为Flase,一直阻塞无法打印
    '''
'''
只有当判断输入q时,才会改变Flag为False,从而结束子线程循环,结束程序
'''
import threading
import time

class MyThread9(threading.Thread):

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

    def run(self):
        global event
        while True:
            if event.isSet():
                print(self.getName() + ' is Running!')
                time.sleep(2)
            else:
                print(self.getName() + ' Stop!!')
                break

event = threading.Event()
event.set()

def func():
    t1 = []
    t1.append(MyThread9())

    for i in t1:
        i.start()
    time.sleep(10)
    q = input('请输入退出:')
    if q == 'q':
        event.clear()
    for i in t1:
        i.join()
    print('all over!!!')
if __name__ == '__main__':
    func() 
posted @ 2019-04-27 23:34  噼里巴啦  阅读(232)  评论(0编辑  收藏  举报