week10-线程及相关线程属性

开启线程的方式一:使用替换threading模块提供的Thread
from threading import Thread
from multiprocessing import Process

def task():
    print('is running')

if __name__ == '__main__':
    t=Thread(target=task,)
    # t=Process(target=task,)
    t.start()
    print('')
View Code
开启线程的方式二:自定义类,继承Thread
from threading import Thread
from multiprocessing import Process
class MyThread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):
        print('%s is running' %self.name)

if __name__ == '__main__':
    t=MyThread('egon')
    # t=Process(target=task,)
    t.start()
    print('')
View Code
线程和进程的pid
from threading import Thread
from multiprocessing import Process
import os

def task():
    print('%s is running' %os.getpid())

if __name__ == '__main__':
    # t1=Thread(target=task,)
    # t2=Thread(target=task,)
    t1=Process(target=task,)
    t2=Process(target=task,)
    t1.start()
    t2.start()
    print('',os.getpid())
View Code

线程共享同一进程内的资源

from threading import Thread
from multiprocessing import Process
n=100
def work():
    global n
    n=0

if __name__ == '__main__':

    # p=Process(target=work,)
    # p.start()
    # p.join()
    # print('主',n)

    t=Thread(target=work,)
    t.start()
    t.join()
    print('',n)
View Code

多线程共享同一进程内地址空间的练习

from threading import Thread
msg_l=[]
format_l=[]
def talk():
    while True:
        msg=input('>>: ').strip()
        msg_l.append(msg)

def format():
    while True:
        if msg_l:
            data=msg_l.pop()
            format_l.append(data.upper())

def save():
    while True:
        if format_l:
            data=format_l.pop()
            with open('db.txt','a') as f:
                f.write('%s\n' %data)

if __name__ == '__main__':
    t1=Thread(target=talk)
    t2=Thread(target=format)
    t3=Thread(target=save)

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

Thread对象其他相关的属性或方法

from threading import Thread,activeCount,enumerate,current_thread
import time
def task():
    print('%s is running' %current_thread().getName())
    time.sleep(2)

if __name__ == '__main__':
    t=Thread(target=task,)
    t.start()
    t.join()
    print(t.is_alive())
    print(t.getName())
    print(enumerate())
    print('')
    print(activeCount())



current_thread的用法
from threading import Thread,activeCount,enumerate,current_thread
from multiprocessing import Process
import time

def task():
    print('%s is running' %current_thread().getName())
    time.sleep(2)

if __name__ == '__main__':
    p=Process(target=task)
    p.start()
    print(current_thread())



from threading import Thread,activeCount,enumerate,current_thread
from multiprocessing import Process
import time

def task():
    print('%s is running' %current_thread().getName())
    time.sleep(2)

if __name__ == '__main__':
    t1=Thread(target=task)
    t2=Thread(target=task)
    t3=Thread(target=task)
    t1.start()
    t2.start()
    t3.start()
    print(current_thread())

#强调:主线程从执行层面上代表了其所在进程的执行过程
View Code

守护线程

# 先看:守护进程

from multiprocessing import Process
import time

def task1():
    print('123')
    time.sleep(1)
    print('123done')

def task2():
    print('456')
    time.sleep(10)
    print('456done')

if __name__ == '__main__':
    p1=Process(target=task1)
    p2=Process(target=task2)
    p1.daemon = True
    p1.start()
    p2.start()
    print('')


#再看:守护线程

from threading import Thread
import time

def task1():
    print('123')
    time.sleep(10)
    print('123done')

def task2():
    print('456')
    time.sleep(1)
    print('456done')

if __name__ == '__main__':
    t1=Thread(target=task1)
    t2=Thread(target=task2)
    t1.daemon=True
    t1.start()
    t2.start()
    print('')
View Code

GIT全局解释器锁

from threading import Thread
n=100
def task():
    print('is running')

if __name__ == '__main__':
    t1=Thread(target=task,)
    t2=Thread(target=task,)
    t3=Thread(target=task,)
    # t=Process(target=task,)
    t1.start()
    t2.start()
    t3.start()
    print('')
View Code

线程的互斥锁

from threading import Thread,Lock
import time
n=100
def work():
    global n
    mutex.acquire()
    temp=n
    time.sleep(0.1)
    n=temp-1
    mutex.release()

if __name__ == '__main__':
    mutex=Lock()
    l=[]
    start=time.time()
    for i in range(100):
        t=Thread(target=work)
        l.append(t)
        t.start()

    for t in l:
        t.join()
    print('run time:%s value:%s' %(time.time()-start,n))
View Code

互斥锁与join的区别,join是整个线程,互斥锁是区域

from threading import Thread,Lock
import time
n=100
def work():
    time.sleep(0.05)
    global n
    temp=n
    time.sleep(0.1)
    n=temp-1


if __name__ == '__main__':
    start=time.time()
    for i in range(100):
        t=Thread(target=work)
        t.start()
        t.join()

    print('run time:%s value:%s' %(time.time()-start,n))


#互斥锁
from threading import Thread,Lock
import time
n=100
def work():
    time.sleep(0.05)
    global n
    mutex.acquire()
    temp=n
    time.sleep(0.1)
    n=temp-1
    mutex.release()

if __name__ == '__main__':
    mutex=Lock()
    l=[]
    start=time.time()
    for i in range(100):
        t=Thread(target=work)
        l.append(t)
        t.start()

    for t in l:
        t.join()
    print('run time:%s value:%s' %(time.time()-start,n))
View Code

GIL与多线程性能讨论

#多进程:
#优点:可以利用多核优势
#缺点:开销大


#多线程:
#优点:开销小
#缺点:不能利用多核优势

from threading import Thread
from multiprocessing import Process
import time
#计算密集型
def work():
    res=1
    for i in range(100000000):
        res+=i

if __name__ == '__main__':
    p_l=[]
    start=time.time()
    for i in range(4):
        # p=Process(target=work) #6.7473859786987305
        p=Thread(target=work) #24.466399431228638
        p_l.append(p)
        p.start()
    for p in p_l:
        p.join()

    print(time.time()-start)


from threading import Thread
from multiprocessing import Process
import time
#IO密集型
def work():
    time.sleep(2)

if __name__ == '__main__':
    p_l=[]
    start=time.time()
    for i in range(400):
        # p=Process(target=work) #12.104692220687866
        p=Thread(target=work) #2.038116455078125
        p_l.append(p)
        p.start()
    for p in p_l:
        p.join()

    print(time.time()-start)
View Code

死锁与递归锁

#死锁现象
from threading import Thread,Lock,RLock
import time
mutexA=Lock()
mutexB=Lock()
class Mythread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutexA.acquire()
        print('\033[45m%s 抢到A锁\033[0m' %self.name)
        mutexB.acquire()
        print('\033[44m%s 抢到B锁\033[0m' %self.name)
        mutexB.release()
        mutexA.release()

    def f2(self):
        mutexB.acquire()
        print('\033[44m%s 抢到B锁\033[0m' %self.name)
        time.sleep(1)
        mutexA.acquire()
        print('\033[45m%s 抢到A锁\033[0m' %self.name)
        mutexA.release()
        mutexB.release()


if __name__ == '__main__':
    for i in range(20):
        t=Mythread()
        t.start()


#递归锁
from threading import Thread,Lock,RLock
import time
mutex=RLock()
class Mythread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutex.acquire()
        print('\033[45m%s 抢到A锁\033[0m' %self.name)
        mutex.acquire()
        print('\033[44m%s 抢到B锁\033[0m' %self.name)
        mutex.release()
        mutex.release()

    def f2(self):
        mutex.acquire()
        print('\033[44m%s 抢到B锁\033[0m' %self.name)
        time.sleep(1)
        mutex.acquire()
        print('\033[45m%s 抢到A锁\033[0m' %self.name)
        mutex.release()
        mutex.release()


if __name__ == '__main__':
    for i in range(20):
        t=Mythread()
        t.start()
View Code

信号量

from threading import Thread,current_thread,Semaphore
import time,random

sm=Semaphore(5)
def work():
    sm.acquire()
    print('%s 上厕所' %current_thread().getName())
    time.sleep(random.randint(1,3))
    sm.release()

if __name__ == '__main__':
    for i in range(20):
        t=Thread(target=work)
        t.start()
View Code

事件Event

from threading import Thread,current_thread,Event
import time
event=Event()

def conn_mysql():
    count=1
    while not event.is_set():
        if count > 3:
            raise ConnectionError('链接失败')
        print('%s 等待第%s次链接mysql' %(current_thread().getName(),count))
        event.wait(0.5)
        count+=1

    print('%s 链接ok' % current_thread().getName())


def check_mysql():
    print('%s 正在检查mysql状态' %current_thread().getName())
    time.sleep(1)
    event.set()


if __name__ == '__main__':
    t1=Thread(target=conn_mysql)
    t2=Thread(target=conn_mysql)
    check=Thread(target=check_mysql)

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

定时器

from threading import Timer


def hello(n):
    print("hello, world",n)


t = Timer(3, hello,args=(11,))
t.start()  # after 1 seconds, "hello, world" will be printed
View Code

线程queue

import queue

q=queue.Queue(3) #队列:先进先出
q.put(1)
q.put(2)
q.put(3)

print(q.get())
print(q.get())
print(q.get())

q=queue.LifoQueue(3) #堆栈:后进先出
q.put(1)
q.put(2)
q.put(3)

print(q.get())
print(q.get())
print(q.get())

q=queue.PriorityQueue(3) #数字越小优先级越高
q.put((10,'data1'))
q.put((11,'data2'))
q.put((9,'data3'))

print(q.get())
print(q.get())
print(q.get())
View Code

进程池与线程池

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import os,time,random
def work(n):
    print('%s is running' %os.getpid())
    time.sleep(random.randint(1,3))
    return n**2

if __name__ == '__main__':
    p=ProcessPoolExecutor()
    # objs=[]
    # for i in range(10):
    #     obj=p.submit(work,i)
    #     objs.append(obj)
    # p.shutdown()
    # for obj in objs:
    #     print(obj.result())

    obj=p.map(work,range(10))
    p.shutdown()
    print(list(obj))




from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import current_thread
import os,time,random
def work(n):
    print('%s is running' %current_thread().getName())
    time.sleep(random.randint(1,3))
    return n**2

if __name__ == '__main__':
    p=ThreadPoolExecutor()
    objs=[]
    for i in range(21):
        obj=p.submit(work,i)
        objs.append(obj)
    p.shutdown()
    for obj in objs:
        print(obj.result())



#进程池
import requests #pip3 install requests
import os,time
from multiprocessing import Pool
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
def get_page(url):
    print('<%s> get :%s' %(os.getpid(),url))
    respone = requests.get(url)
    if respone.status_code == 200:
        return {'url':url,'text':respone.text}

def parse_page(obj):
    dic=obj.result()
    print('<%s> parse :%s' %(os.getpid(),dic['url']))
    time.sleep(0.5)
    res='url:%s size:%s\n' %(dic['url'],len(dic['text'])) #模拟解析网页内容
    with open('db.txt','a') as f:
        f.write(res)


if __name__ == '__main__':

    # p=Pool(4)
    p=ProcessPoolExecutor()
    urls = [
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
    ]


    for url in urls:
        # p.apply_async(get_page,args=(url,),callback=parse_page)
        p.submit(get_page,url).add_done_callback(parse_page)

    p.shutdown()
    print('主进程pid:',os.getpid())


# 线程池
import requests #pip3 install requests
import os,time,threading
from multiprocessing import Pool
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
def get_page(url):
    print('<%s> get :%s' %(threading.current_thread().getName(),url))
    respone = requests.get(url)
    if respone.status_code == 200:
        return {'url':url,'text':respone.text}

def parse_page(obj):
    dic=obj.result()
    print('<%s> parse :%s' %(threading.current_thread().getName(),dic['url']))
    time.sleep(0.5)
    res='url:%s size:%s\n' %(dic['url'],len(dic['text'])) #模拟解析网页内容
    with open('db.txt','a') as f:
        f.write(res)


if __name__ == '__main__':

    # p=Pool(4)
    p=ThreadPoolExecutor(3)
    urls = [
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
        'http://www.baidu.com',
    ]


    for url in urls:
        # p.apply_async(get_page,args=(url,),callback=parse_page)
        p.submit(get_page,url).add_done_callback(parse_page)

    p.shutdown()
    print('主进程pid:',os.getpid())
View Code

并发编程重要的知识点

1 生产者消费者模型
2 进程池线程池
3 回调函数
4 GIL全局解释器锁

posted @ 2017-09-07 16:17  warren1236  阅读(126)  评论(0)    收藏  举报