11.python并发入门(part2 threading模块的基本使用)

一、在使用python多线程之前,你需要知道的。

python的多线程中,实现并发是没有问题的,但是!!是无法实现真正的并行的。

这是因为python内部有个GIL锁(全局解释器锁),这个锁限制了在同一时刻,同一个进程中,只能有一个线程被运行!!!

二、threading模块的基本使用方法。

可以使用它来创建线程。有两种方式来创建线程。

1、通过继承Thread类,重写它的run方法。

2、创建一个threading.Thread对象,在它的初始化函数__init__中将可调用对象作为参数传入。

3、接下来演示下这两种创建线程对象的方法。

  1. 通过继承Thread类的方式创建线程。

#!/usr/local/bin/python2.7

# -*- coding:utf-8 -*-

import threading

import  time

class Mythread(threading.Thread):

def __init__(self,num):

threading.Thread.__init__(self)

self.num = num

def run(self):

print "running number %s" %(self.num)

time.sleep(3)

t1 = Mythread(1111111)

t2 = Mythread(2222222)

t1.start()    #调用线程对象的start方法,类中的run方法就会被执行!!!!

t2.start()

print "ending"

2.创建一个threading.Thread对象,在实例化对象时调用构造方法来创建线程。

import threading

import  time

def print_num(num):

print "running num is %s" %(num)

time.sleep(3)

print "running num is %s over!!!!" %(num)

if __name__ == "__main__":

t1 = threading.Thread(target=print_num,args=(111111,))  #创建线程对象

t2 = threading.Thread(target=print_num,args=(222222,)) #创建线程对象。

t1.start()  #运行线程对象

t2.start()

print "ending"

#当前执行的python程序是一个主线程,在程序中执行的两个线程就是子线程。

三、关于线程对象的一些常用方法。

  1. join()执行了线程的join方法后,在子线程运行结束之前,父线程会被一直阻塞。

import threading

import  time

def listen_music(name):

print "begin listenning to %s.%s" %(name,time.ctime())

time.sleep(3)

print "end listenning time %s" %(time.ctime())

def play_game(name):

print "play %s time %s " %(name,time.ctime())

time.sleep(8)

print "end playing"

thread_list = []

t1 = threading.Thread(target=listen_music,args=("mirrorcle world",))

t2 = threading.Thread(target=play_game,args=("Virtual stalker",))

t1.start()

t1.join()   #当t1没有执行完之前,父线程会被阻塞,直到t1执行结束后,主线程(主程序)的代码才会继续执行。

t2.start()

t2.join()  #当t2没有执行完之前,父线程会被阻塞,直到t2执行结束后主线程(主程序)的代码才会继续执行。

print "ending......."

2.setdeamon()设置守护线程。

首先先来了解下守护线程的概念。

我们用python写的程序,在运行的过程中,会开启一个主线程,如果这个主线程开启了一个子线程,主线程和子线程会兵分两路,分别运行。

默认情况下,当我们的python程序运行结束,准备退出的时候,会校验子线程是否运行完毕,如果子线程没有运行完毕,主线程会等待子线程运行完毕后,在退出,这是默认情况。

假如,我们现在有一种需求,只需要主线程运行结束后,不管子线程是否运行结束,都要和主线程一起结束,这就是守护线程的概念。

import threading

import  time

def listen_music(name):

print "begin listenning to %s.%s" %(name,time.ctime())

time.sleep(3)

print "end listenning time %s" %(time.ctime())

def play_game(name):

print "play %s time %s " %(name,time.ctime())

time.sleep(8)

print "end playing"

thread_list = []

t1 = threading.Thread(target=listen_music,args=("mirrorcle world",))

t2 = threading.Thread(target=play_game,args=("Virtual stalker",))

t1.setDaemon(True)  #守护线程一定要设置在start之前!!!

t1.start()

t2.setDaemon(True)

t2.start()

print "ending......."

运行结果:

begin listenning to mirrorcle world.Thu May 11 10:26:23 2017

play Virtual stalker time Thu May 11 10:26:23 2017

ending.......

从结果中可以看出两个线程的内容并没有被执行完!主线程执行结束后,子线程也跟着结束了!

四、关于线程对象的一些其他方法。

isAlive() 用来判断一个线程是否处于活动状态。

getName() 返回这个线程的线程名称。

setName()设置一个线程的名称。

threading 模块提供的一些函数:

threading.currentThread()返回当前线程对象。

threading.enumerate()  将当前python程序中正在运行的线程对象,以列表的形式返回。

threading.activeCount() 返回当前运行的线程数量。

时间: 2024-11-05 21:50:41

11.python并发入门(part2 threading模块的基本使用)的相关文章

11.python并发入门(part5 event对象)

一.引入event. 每个线程,都是一个独立运行的个体,并且每个线程的运行状态是无法预测的. 如果一个程序中有很多个线程,程序的其他线程需要判断某个线程的运行状态,来确定自己下一步要执行哪些操作. threading模块中的event对象恰好能做到这一点,event对象包含了一个可以通过线程设置的一个信号标志位,它允许线程一直等待某些事件的发生. 在初始化默认的情况下,event对象中的信号标识被设置为"假",如果这时,有一个线程等待这个event对象,而这个event对象的信号标志为

11.python并发入门(part9 多线程模块multiprocessing基本用法)

一.回顾多继承的概念. 由于GIL(全局解释器锁)的存在,在python中无法实现真正的多线程(一个进程里的多个线程无法在cpu上并行执行),如果想充分的利用cpu的资源,在python中需要使用进程. 二.multiprocessing模块的简介. multiprocessing是python中用来管理多进程的包,与threading用法非常类似,它主要使用multiprocessing.Process对象来创建一个进程对象,该进程可以运行在python的函数中. 该Process(进程)对象

11.python并发入门(part12 初识协程)

一.协程的简介. 协程,又被称为微线程,虽然是单进程,单线程,但是在某种情况下,在python中的协程执行效率会优于多线程. 这是因为协程之间的切换和线程的切换是完全不一样的!协程的切换是由程序自身控制的(程序的开发者使用yield去进行控制,协程和协程之间的切换是可控制的,想什么时候切换就什么时候切换). 当使用多线程时,开的线程越多,协程的优势就越明显. 协程的另一个优点,就是无需锁机制,因为协程只有一个进程,和线程,不存在多线程或者多进程之间访问公共资源的冲突,所以说,在协程中无需加锁,如

11.python并发入门(part7 线程队列)

一.为什么要用队列? 队列是一种数据结构,数据结构是一种存放数据的容器,和列表,元祖,字典一样,这些都属于数据结构. 队列可以做的事情,列表都可以做,但是为什么我们还要去使用队列呢? 这是因为在多线程的情况下,列表是一种不安全的数据结构. 为什么不安全?可以看下面这个例子: #开启两个线程,这两个线程并发从列表中移除一个元素. import threading import time l1 = [1,2,3,4,5] def pri(): while l1: a = l1[-1] print a

11.python并发入门(part4 死锁与递归锁)

一.关于死锁. 死锁,就是当多个进程或者线程在执行的过程中,因争夺共享资源而造成的一种互相等待的现象,一旦产生了死锁,不加人工处理,程序会一直等待下去,这也被称为死锁进程. 下面是一个产生"死锁"现象的例子: import threading import time lock_a = threading.Lock() lock_b = threading.Lock() class test_thread(threading.Thread): def __init__(self): su

11.python并发入门(part15 关于I/O多路复用)

一.为什么要产生I/O多路复用? 两个主机之间通信,主机A和主机B都需要开启socket,主机A首先要等待客户端来进行连接,这是会发起一个recvfrom的系统调用,如果主机B一直没有去连接主机A,没有给主机A发送任何数据,进程就会被阻塞,无法去做其他的事情(默认的阻塞I/O模型),一直阻塞到主机B去连接主机A,主机A收到了这个连接. 其实这种模式在单服务器,单客户端(两台主机之间单独通信)没有什么问题,如果说是多并发场景呢?服务端阻塞与第一个客户端发来的socket对象中,另外一个客户端2要发

11.python并发入门(part6 Semaphore信号量)

一.什么是信号量. 信号量也是一种锁. 信号量的主要用途是用来控制线程的并发量的,BoundedSemaphore或Semaphore管理一个内置的计数器,每调用一次acquire()方法时,计数器-1,每调用一次release()方法时,内部计数器+1. 不过需要注意的是,Semaphore内部的计数器不能小于0!当它内部的计数器等于0的时候,这个线程会被锁定,进入阻塞状态,直到其他线程去调用release方法. BoundedSemaphore与Semaphore的唯一区别在于前者将在调用r

11.python并发入门(part3 多线程与互斥锁)

一.锁的概念. 锁,通常被用来实现共享数据的访问,为每一个共享的数据,创建一个Lock对象(一把锁),当需要访问这个共享的资源时,可以调用acquire方法来获取一个锁的对象,当共享资源访问结束后,在调用release方法去解锁. 二.python中的互斥锁. 在介绍互斥锁之前,先来一起看一个例子.(每个线程对num实现一次-1的操作) import threading import  time num = 200  #每个线程都共享这个变量. tread_list = [] def count

11.python并发入门(part8 基于线程队列实现生产者消费者模型)

一.什么是生产者消费者模型? 生产者就是生产数据的线程,消费者指的就是消费数据的线程. 在多线程开发过程中,生产者的速度比消费者的速度快,那么生产者就必须等待消费者把数据处理完,生产者才会产生新的数据,相对的,如果消费者处理数据的速度大于生产者,那么消费者就必须等待生产者. 为了解决这种问题,就有了生产者消费者模型. 生产者与消费者模型,是通过一个容器,来解决生产者和消费者之间的耦合性问题,生产者和消费者之间并不会直接通信,这样生产者就无需等待消费者处理完数据,生产者可以直接把数据扔给队列,这个