python day9

本节内容

进程与线程

1.进程:

程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。

在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。

进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率。很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上:

  • 进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。

  • 进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。

2.线程:

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务

Python threading模块

线程有2种调用方式,如下:

直接调用

# 直接调用
import time
import threading
def run(name):
    print('%s线程执行.....'%name)
    time.sleep(3)
    pass

t1 =threading.Thread(target=run,args=('A',))
t2 =threading.Thread(target=run,args=('B',))
t1.start()
t2.start()
View Code

继承调用

# 继承式
import time
import threading

class MyThread(threading.Thread):
     def __init__(self,name):
         super(MyThread,self).__init__()
         self.name=name
         pass

     def run(self):

        print("running is thread %s"%self.name)
        time.sleep(3)
        pass



t1=MyThread('C')
t2=MyThread('D')
t1.start()
t2.start()
View Code

join:等待线程终止。(线程的合并)

import time
import threading

class MyThread(threading.Thread):
     def __init__(self,name):
         super(MyThread,self).__init__()
         self.name=name
         pass

     def run(self):

        print("running is thread %s"%self.name)
        time.sleep(3)
        pass



t1=MyThread('C')

t2=MyThread('D')
t1.start()#等待t1线程执行完毕在执行t2线程
t1.join()
t2.start()
View Code

Daemon:设置线程为守护线程

守护线程是:辅助线程,当一个线程为另一个线程的守护线程时,那么如果另一个线程退出,那么守护线程也会退出,在守护线程中开启的线程也会同时退出。

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:Dragon war
# datetime:2018/9/6 23:44
# software: PyCharm

# 守护线程
import time
import threading
class MyThread(threading.Thread):
    def __init__(self, name):
        super(MyThread, self).__init__()
        self.name = name
        pass

    def run(self):
        print("running is thread %s" % self.name)
        time.sleep(3)
        pass


t1 = MyThread('C')

t2 = MyThread('D')
t1.setDaemon(True)#设置线程为守护线程。
t2.setDaemon(True)
t1.start()
t2.start()


print('mian 主线程执行完毕')
View Code

线程锁

   线程锁指的是:我们多线程在同时修改一个数据时,每个线程都会拿到同一份数据,那么修改完后数据的结果就会不正确了。

import threading
import time


num=0
def run(n):

   global num
   if n=='A':
    time.sleep(2)
    num+=1
    print("num", num)

   else:
       num+=1

       print("num", num)
pass




t1 = threading.Thread(target=run,args='A')
t2=threading.Thread(target=run,args='B')

t1.start()
t2.start()
View Code

加锁后的代码:

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:Dragon war
# datetime:2018/9/7 13:34
# software: PyCharm

import threading
import time
# 获取一个锁的实例
lock =threading.Lock()
num=0
def run(n):

   global num
   lock.acquire()#加锁
   if n=='A':
    print("A",num)#线程A获取的num的值
    time.sleep(2)

    num+=1
    print("A修改后num", num)
    lock.release()#释放锁

   else:
       print("B:",num) #线程B获取的num的值
       num+=1

       print("B修改后num", num)
       lock.release()
pass




t1 = threading.Thread(target=run,args='A')
t2=threading.Thread(target=run,args='B')

t1.start()
t2.start()
View Code

注意:在python3上有锁没锁,代码结果都是正确的,可能是python3自动加了锁。

递归锁:

我们可能在使用线程锁的时候,可能出现锁中套者锁,那么这个时候就可能出现,线程退不出来。

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:Dragon war
# datetime:2018/9/7 14:33
# software: PyCharm


# 递归锁
import threading,time

def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num +=1
    lock.release()
    return num
def run2():
    print("grab the second part data")
    lock.acquire()
    global  num2
    num2+=1
    lock.release()
    return num2
def run3():
    lock.acquire()
    res = run1()
    print('--------between run1 and run2-----')
    res2 = run2()
    lock.release()
    print(res,res2)



num,num2 = 0,0
lock = threading.Lock()
for i in range(10):
  t = threading.Thread(target=run3)
  t.start()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print('----all threads done---')
    print(num,num2)
View Code

使用递归锁

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:Dragon war
# datetime:2018/9/7 14:33
# software: PyCharm


# 递归锁
import threading,time

def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num +=1
    lock.release()
    return num
def run2():
    print("grab the second part data")
    lock.acquire()
    global  num2
    num2+=1
    lock.release()
    return num2
def run3():
    lock.acquire()
    res = run1()
    print('--------between run1 and run2-----')
    res2 = run2()
    lock.release()
    print(res,res2)



num,num2 = 0,0
lock = threading.RLock()
for i in range(10):
  t = threading.Thread(target=run3)
  t.start()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print('----all threads done---')
    print(num,num2)
View Code

Semaphore(信号量)

互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据。

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:Dragon war
# datetime:2018/9/7 14:42
# software: PyCharm

import threading,time

def run(n):
    semaphore.acquire()
    global num
    num+=1
    time.sleep(1)

    print("run the thread: %s" %n,num,'
')
    semaphore.release()

if __name__ == '__main__':

    num= 0
    semaphore  = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
    for i in range(20):
        t = threading.Thread(target=run,args=(i,))
        t.start()

while threading.active_count() != 1:
    pass #print threading.active_count()
else:
    print('----all threads done---')
    print(num)
View Code

Events

Event(事件)是最简单的线程通信机制之一:一个线程通知事件,其他线程等待事件。Event内置了一个初始为False的标志,当调用set()时设为True,调用clear()时重置为 False。wait()将阻塞线程至等待阻塞状态。

isSet(): 当内置标志为True时返回True。 
  set(): 将标志设为True,并通知所有处于等待阻塞状态的线程恢复运行状态。 
  clear(): 将标志设为False。 
  wait([timeout]): 如果标志为True将立即返回,否则阻塞线程至等待阻塞状态,等待其他线程调用set()。

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:Dragon war
# datetime:2018/9/7 16:26
# software: PyCharm

# 红绿等
import threading
import time

event=threading.Event()

def run():
    count=0;
    while True:
        if count>5 and count<10:
            event.clear()
            print('这是红灯请等待')
        elif count>10:
            event.set()
            count=0
        else:
            print('这是绿灯,请通行')

        time.sleep(1)
        count+=1
    pass

def car(name):

    while True:
        if event.is_set():
            print('请 赶紧通行',name)
        else:
            print("请等待红灯")
            event.wait()
    pass

h=threading.Thread(target=run,)
c=threading.Thread(target=car,args=('奔驰',))
c1=threading.Thread(target=car,args=('宝马',))
h.start()
c.start()
c1.start()
View Code

队列:

queue

queue是用户多线程编程中的,线程之间的通信。

python中有3种队列:

class queue.Queue(maxsize=0) #先入先出
class queue.LifoQueue(maxsize=0) #last in fisrt out 
class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列
queue常用的方法:
将一个值放入队列中 put方法
将一个值从队列中取出 get方法

q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)
非阻塞 q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号

q.join() 实际上意味着等到队列为空,再执行别的操作

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:Dragon war
# datetime:2018/9/10 14:16
# software: PyCharm

# 队列 queue

# 队列使用queue模块

import queue


# 创建队列:先进先出
q=queue.Queue()
# 往队列中添加
q.put(1)
q.put(2)

# 队列大小

print(q.qsize())

# 从队列中取值

print(q.get())
print(q.get())
# 如果队列中没有值了,那么再调用get方法,将会阻塞

print(q.get())
while not  q.empty():

    print(q.get())

qe=queue.LifoQueue()  #先进后出

for i in range(5):
    qe.put(i)
    pass

# 取值
while not  qe.empty():

    print(qe.get())


# 优先级队列

qq =queue.PriorityQueue()
# 添加
qq.put(10,"aaa")
qq.put(6,"bbbb")
qq.put(12,"cccc")
qq.put(3,"ddddd")

# 取值
while not qq.empty():

    print(qq.get())

    pass
View Code
原文地址:https://www.cnblogs.com/wuzhilong/p/9599607.html