Python 线程相关内容

线程
  *线程也是多任务编程的一种方法,可以使用计算机多核资源
  *线程又称为轻量级的进程,在创建和删除时消耗的计算机资源小

  线程和进程关系:
    *一个进程中可以包含多个线程
    *进程中的所有线程共享进程的空间资源(空间,全局变量,分配的内存等)
    *线程也有自己的特有属性,比如:指令集 TID等

  创建线程
    import threading 
      t=threading.Tread()
      Thread()
        功能:创建线程
        参数:target 线程函数
             args   元组 给线程函数位置传参
             kwargs 字典 给线程函数字典传参
             name 给线程取名字 (默认Thread-1)
        返回值:线程对象

      t.start() 启动线程
      t.join(timeout) 回收线程
      t.is_alive() 查看线程状态
      t.name 查看线程名称
      threading.currentThread() 得到线程对象
      t.setName() 设置属性名称
      t.daemon 属性
      默认为False 主线程执行完毕不会影响分支线程的执行
        设为True 主线程执行完毕,其他线程也会终止

      t.isDaemon():判断 deamon属性时True or False


      设置方法:
        t.daemon=True
        t.setDaemon(True)

示例一:

import threading 
from time import sleep
def music():
    while True:
        sleep(2)
        print("播放《活着》")
def sing():
    while True:
        sleep(2)
        print("kjkjk")
#创建线程和函数music关联
t=threading.Thread(target=music)
a=threading.Thread(target=sing)
#启动线程
t.start()
a.start()
while True:
    sleep(1.5)
    print("想听《花海》")
print("=======")
t.join()
a.join()

示例二:

#线程属性
from threading import Thread,currentThread
from time import sleep
def fun(sec):
    print("线程属性测试")
    sleep(sec)
    print("%s线程结束"%currentThread().getName())

thread=[]
for i in range(3):
    t=Thread(name='tedu'+str(i),target=fun,args=(5,))
    t.start()
    thread.append(t)

for i in thread:
    print("thread name :",i.name)
    print("alive :",i.is_alive())
    i.join()

 示例三:

#daemon属性
from threading import Thread
from time import sleep
def fun():
    print("Daemon 属性测试")
    sleep(5)
    print("线程结束")
t=Thread(target=fun)
#为线程设置名字
t.setName('tedu')
#daemon属性设置为True
#t.daemon=True
t.setDaemon(True)#将daemon属性设置为True
print(t.isDaemon())
t.start()
t.join(2)
print("=====主线程结束=======") 

线程间通信
    通过全局变量进行通信

示例:

from threading import Thread
from time import sleep
#全局变量a
#通过全局变量进行通信
a=1
def foo():
    global a
    #将全局变量a做修改
    a=1000
def bar():
    sleep(1)
    #此时全局变量a改变,变为100
    print("a=",a)#a=1000

t1=Thread(target=foo)
t2=Thread(target=bar)
t1.start()
t2.start()
t1.join()
t2.join()
print(a)

    进程和线程的区别和联系
      两者都是多任务编程方式,均可使用计算机的多核
      进程的创建要比线程消耗更多的资源
      进程空间独立,数据安全性更好操作,有专门的进程间通信方式
      线程使用全局变量通信,往往要和同步互斥机制配合防止产生资源的争夺
      一个进程可以包含多个线程,线程共享进程资源
      进程线程都有自己的特有资源

    使用场景
      需要创建较多的并发,任务比较简单,线程比较合适
      如果程序间数据资源使用重叠比较多,要考虑到线程锁是否需要更复杂的逻辑
      如果多个任务并无什么关联,不易用多线程将其融入到一个进程中
      python线程不适用计算密集型并发

  创建自定义线程类
    继承Thread类
    重写 run 方法
    from threading import Thread
    from time import ctime,sleep
    
    #编写自己的线程类
    class Mythread(Thread):
        def __init__(self,func,args,name='Tedu'):
            # Thread.__init__(self)
            super().__init__()
            self.func=func
            self.args=args
            self.name=name
        #调用start会自动运行
        def run(self):
            self.func(*self.args)
    def player(file,sec):
        for i in range(2):
            print("playing %s :%s"%(file,ctime()))
            sleep(sec)
    t=Mythread(player,('baby.mp3',3))
    t.start()
    t.join()

示例:

from threading import Thread
from time import ctime,sleep
#编写自己的线程类
class Mythread(Thread):
    def __init__(self,func,args,name='Tedu'):
        #如果没有执行父类__init__方法
        # Thread.__init__(self)
        super().__init__()
        self.func=func
        self.args=args
        self.name=name
    #调用start会自动运行
    #重写run方法
    def run(self):
        player()     args=('baby.mp3',3)
        self.func(*args)
def player(file,sec):
    for i in range(2):
        print("playing %s :%s"%(file,ctime()))
        sleep(sec)
t=Mythread(player,('baby.mp3',3))
t.start()
t.join()

  线程中同步互斥方法
  Event 线程事件
      e=Event()
        e.wait()  e.set()  e.clear()

示例:

import threading
from time import sleep
s=None
#创建线程对象
e=threading.Event()
def fun1():
    print("和fun2进行沟通")
    global s
    s="天街小雨润如酥"
def fun2():
    print("等待口令")
    sleep(2)
    if s == "天街小雨润如酥":
        print("fun2收到",s)
    else:
        print("口令有误")
    e.set()
def fun3():
    print("改掉口令")
    sleep(1)
    e.wait()#阻塞
    global s
    s="不下了"#想要将全局变量s改为"不下了",导致fun2接受的消息将发生改变
t1=threading.Thread(name='fun1',taregt=fun1)
t2=threading.Thread(name='fun2',taregt=fun2)
t3=threading.Thread(name='fun3',taregt=fun3)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()

    Lock  线程锁
      t=Loce() 创建锁
        t.acquire() 加锁
        t.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()#解锁

t=threading.Thread(target=value)
t.start()
while True:
    lock.acquire()
    a+=1
    b+=1
    lock.release()
t.join()


    Condition

示例:

import threading
import time
import datetime

num=0

#条件变量
con=threading.Condition()
class Gov(threading.Thread):
    def run(self):
        global num
        con.acquire()
        while True:
            print("开始拉升股市")
            num+=1
            print("拉升了%d个点"%num)
            time.sleep(2)
            if num==5:
                print("暂时安全")
                con.notify()
                print("不操作")
                con.wait()
        con.release()
class Consumers(threading.Thread):
    def run(self):
        global num
        con.acquire()
        while True:
            if num>0:
                print("开始打压股市")
                num-=1
                print("下降了%d个点"%num)
                time.sleep(2)
                if num==0:
                    print("天台在哪,我要自杀")
                    con.notify()
                    print("不能再下降了")
                    con.wait()
        con.release()
t1=Gov()
t2=Consumers()
t1.start()
t2.start()

python线程之GIL
(全局解释器锁)
python ---->支持多线程---->同步互斥---->加锁--->超级锁--->在同一时刻,解释器只能解释一个线程---->大量python库为了省事沿用了这种方法--->python 多线程效率低下
GIL问题:由于python的全局解释器锁造成python的多线程执行效率低下
解决方法:
*不使用线程,使用多进程
*不适用C C++ 做解释器 C#  Java也可以做解释器
*python线程适合高用时的IO操作,网络IO,不适合cpu密集型程序

多线程并发


相比多进程并发:
劣势:

1.可能需要同步和互斥的机制
2.受到GIL的影响
优势: 只需要消耗较少的系统资源
步骤:
1.创建套接字
2.准备接收客户端连接
3.每当有一个客户端链接进来就创建一个新的线程
4.客户端退出后结束相应线程,关闭客户端套接字

from socket import *

from threading import *
import os,sys
#处理具体的客户端请求
def handler(connfd):
    print("Got connection from ",connfd.getpeername())
    while True:
        data=connfd.recv(1024).decode()
        if not data:
            break
        connfd.send(b"receive your message")
    connfd.close()

HOST='172.60.16.43'
PORT=8814
#创建套接字
s=socket()
s.bind((HOST,PORT))
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.listen(5)
#主线程循环接受客户端连接
while True:
    try:
        c,addr=s.accept()
    except KeyboardInterrupt:
        raise
    except Exception as e:
        print(e)
        continue
    t=Thread(target=handler,args=(c,))
    t.setDaemon(True)
    t.start()

s.close()

猜你喜欢

转载自blog.csdn.net/Shen1105/article/details/81158706