码迷,mamicode.com
首页 > 编程语言 > 详细

python学习_day36_并发编程之多线程1

时间:2017-10-13 18:58:30      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:sel   工作过程   count   任务   self   函数   cpu   log   比较   

一、多线程相关概念

1.线程的定义

  在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程,线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程。车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线,流水线的工作需要电源,电源就相当于cpu。所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

  多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。

2.线程的特点

  开销小的特点:类比车间与流水线的关系,开启进程需要申请一个空间,并至少开启一条流水线(线程),而线程只是在车间(进程)中开一条流水线,不需要申请空间。

3.多线程应用

  多线程指的是,在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程。详细的讲分为4点:

  (1)多线程共享一个进程的地址空间。

       (2)线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用。

      (3)若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。

      (4)在多cpu系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多。(并不适用于python)

二、开启线程的方式

  方式一:

from threading import Thread
def work(n):
    print(%s is running %n)
if __name__ == __main__:
    for i in range(4):
        t=Thread(target=work,args=(i,))
        t.start()
    print()
‘‘‘
输出结果为:
0 is running
1 is running
2 is running
3 is running
主
‘‘‘

  方式二:

from threading import Thread
class Mythread(Thread):
    def __init__(self,n):
        super().__init__()
        self.n=n
    def run(self):
        print(%s is running %self.n)

if __name__ == __main__:
    for i in range(4):
        t=Mythread(i)
        t.start()
    print()
‘‘‘
输出结果为:
0 is running
1 is running
2 is running
3 is running
主
‘‘‘

三、方法及实例

1、线程共享进程中的资源

 

from threading import Thread
n=100
def work():
    global n
    n=0
if __name__ == __main__:
    t=Thread(target=work)
    t.start()
    t.join()
    print(n)  #输出结果:0

 

  结果分析:t线程执行完成后将主进程中的n进行了更改,并得以保存下来,所以当执行完线程t后,主进程打印得到n的结果为0

from multiprocessing import Process
import time
n=100
def work():
    time.sleep(1)
    global n
    n=0
if __name__ == __main__:
    p=Process(target=work)
    p.start()
    p.join()
    print(n)  #输出结果:100

  结果分析:进程的特点是彼此间是独立的空间,故开启子进程p的时候,将主进程的内容进行了单独的拷贝,子进程执行函数时,是将自己拷贝内容的n进行了更改,而打印主进程中的n时,n值不会发生变化。

2、运行速度比较

  同一进程开多线程情况:

import os
from threading import Thread
def work(n):
    print(子线程%s:%s %(n+1,os.getpid()))
if __name__ == __main__:
    for i in range(2):
        t=Thread(target=work,args=(i,))
        t.start()
    print(主进程:%s%os.getpid())
‘‘‘
子线程1:8784
子线程2:8784
主进程:8784
‘‘‘

  结果分析:从以上结果可以看出,线程的执行速度很快,线程开启就瞬间完成执行,故先打印子线程中的内容,最后才打印主进程中的内容,且线程中pid与进程一致。  

  同一进程开多进程情况:

import os
from multiprocessing import Process
def work(n):
    print(子进程%s:%s %(n+1,os.getpid()))
if __name__ == __main__:
    for i in range(2):
        p=Process(target=work,args=(i,))
        p.start()
    print(主进程:%s%os.getpid())
‘‘‘
主进程:7208
子进程1:8024
子进程2:4072
‘‘‘

  结果分析:由于进程间彼此之间是独立的空间,开启进程的损耗比线程大,所以在主进程中发出开启子进程后,子进程未执行完,主进程便打印出主进程内容,且各进程的pid各不相同。

3、线程主要方法实例

from threading import Thread,current_thread,enumerate,activeCount

def work():
    print(%s is running %(current_thread().getName()))  #获取当前线程的名字
if __name__ == __main__:
    t=Thread(target=work)
    t.start()
    print(enumerate())                                    #当前活跃线程
    print(activeCount())                                  #当前活跃线程数量
    t.join()

四、守护线程 

  无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁,需要强调的是:运行完毕并非终止运行。对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕。

  实例:

from threading import Thread
import time
def foo():
    print(123)
    time.sleep(5)
    print(end123)
def bar():
    print(start456)
    time.sleep(3)
    print(end456)
if __name__ == __main__:
    t1=Thread(target=foo)
    t2=Thread(target=bar)
    t1.daemon=True  #必须放在start()前
    t1.start()
    t2.start()
    print(main)
‘‘‘
123
start456
main
end456
‘‘‘

  结果分析:t1为守护线程,与守护进程不一样(主进程代码结束,则就结束守护进程),主线程代码结束后待非守护线程代码都执行完成,才能结束守护线程。

 

 

 

 

 

  

 

python学习_day36_并发编程之多线程1

标签:sel   工作过程   count   任务   self   函数   cpu   log   比较   

原文地址:http://www.cnblogs.com/seven-007/p/7662298.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!