#线程的创建
from threading import Thread
import time
def func(name):
    time.sleep(1)
    print(f'{name} say hello')
if __name__ == '__main__':
    t = Thread(target=func,args=('tom',))
    t. start()
    print('主线程')
#主线程 很快就打印出来,过了不到1s 才打印tom say hello
#线程的开启很快,线程有没有join?
#线程join
from threading import Thread,enumerate as en
import time
def func(name):
    time.sleep(1)
    print(f'{name} say hello')
if __name__ == '__main__':
    t = Thread(target=func,args=('tom',))
    t. start()
    print(en()) #先打印2个正在执行的线程 threading 里的enumerate 用于罗列当前存活的线程
    t.join()
    print(en()) #现在打印只有1个主线程存活MainThread
    print('主线程') #join了以后 等待线程结束才执行主线程
# [<_MainThread(MainThread, started 13796)>, <Thread(Thread-1, started 13104)>]
# tom say hello
# [<_MainThread(MainThread, started 13796)>]
# 主线程.....
#用自定义类创建线程
from threading import Thread
import time
class MyThread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name
    def run(self):
        time.sleep(1)
        print(f'{self.name} say hello')
if __name__ == '__main__':
    t = MyThread('tom')#可以方便的传参,但是调用函数不够灵活,必须写在类的run方法中
    t.start()
    print('MainThread')
#同一个进程开启的线程拥有相同的进程id 和不同的线程id
from threading import Thread
from multiprocessing import  Process
import os
def func():
    print(os.getpid())
if __name__ == '__main__':
    t1 = Thread(target=func)
    t2 = Thread(target=func)
    t1.start()
    t2.start()

    p1 = Process(target=func)
    p2 = Process(target=func)
    p1.start()
    p2.start()

    print(f'主进程id{os.getpid()}')
# 13476
# 13476
# 主进程id13476 (前面2个线程 和主进程的进程id 一致)
# 3352
# 13452 (后面2个进程id不同而且与主进程进程id不同)
#开启子进程和子线程效率对比
from threading import Thread
from multiprocessing import  Process
import os
def func():
    print(os.getpid())
if __name__ == '__main__':
    p1 = Process(target=func)
    p1.start() #虽然是先开启的子进程,但是还是子线程先打印了结果
    t1 = Thread(target=func)
    t1.start()
    p1.join()
    t1.join()
    print(f'主进程id是:{os.getpid()}')
# 12636  (这是子线程的打印,因为子线程所在进程id和主线程所在进程id一致)
# 12104   (这是子进程id)
# 主进程id是:12636
#子线程共享主进程数据
from threading import Thread
n=1
def func():
    global n
    n=0
if __name__ == '__main__':
    t1 = Thread(target=func)
    t1.start()
    t1.join()
    print('主进程的n:',n) #主进程的n: 0
#多线程实现socket
#server端
from threading import Thread
import socket
def func(conn):
    while 1: #这里while 是可以循环聊天
        msg = conn.recv(1024).decode('utf-8')
        conn.send(msg.upper().encode('utf-8'))
    conn.close()
if __name__ == '__main__':
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9002))
    sk.listen()
    while 1: #这里while 是接收多个客户端连接
        conn,addr= sk.accept()
        t = Thread(target=func,args=(conn,))
        t.start()
    sk.close()
#client端
import socket
sk = socket.socket()
sk.connect(('127.0.0.1', 9002))
while 1:
    msg = input('>>>')
    sk.send(msg.encode('utf-8'))
    msg = sk.recv(1024).decode('utf-8')
    print(msg)
sk.close()
#获取当前代码所在线程的线程名
from threading import Thread
import threading
from multiprocessing import Process
import time
def func():
    time.sleep(1)
    print(threading.current_thread().getName()) #先打印线程名  :Thread-1,这里的current_thread是可以获取当前代码所在的线程,返回线程对象
if __name__ == '__main__':
    t = Thread(target=func)
    t.start()
    t.join()
    print(threading.current_thread().getName()) #线程结束打印主线程名
    print(threading.current_thread()) #打印当前代码所在线程
    print(threading.enumerate()) #打印所有线程,列表,只剩下主线程了
    print(threading.active_count())#打印活动的线程个数,只有主线程了
# Thread-1
# MainThread
# <_MainThread(MainThread, started 5740)>
# [<_MainThread(MainThread, started 5740)>]
# 1
#线程的is_alive方法和 join方法
import threading
import time
def func():
    time.sleep(1)
if __name__ == '__main__':
    t = threading.Thread(target=func)
    t.start()
    print(t.is_alive()) #True is_alive 判断线程是否存活
    t.join() #join 等子线程结束再执行主线程代码
    print('主线程')
    print(t.is_alive()) #False
#守护线程的设置 setDaemon(True)
from threading import Thread
import time
def func():
    time.sleep(1)
    print('hello')
if __name__ == '__main__':
    t = Thread(target=func)
    t.setDaemon(True) #守护线程必须在启动之前设置
    t.start()
    print('主线程') #结果就没有打印hello ,只打印了‘主线程’ 守护线程被强制停止了
#如果把t.setDaemon(True)注释掉,不设置守护线程,结果就是先打印‘主线程’,再打印‘hello’,主进程等守护线程也结束才回收了资源
#如果设置2个线程对比一下看时间
from threading import Thread
import time
def func():
    time.sleep(3)
    print('hello1')
def func2():
    time.sleep(1)
    print('hello2')
if __name__ == '__main__':
    t = Thread(target=func) #func 被安排到守护线程里,sleep的比较久,结果并没有执行,还是在
    t.setDaemon(True)
    t.start()
    t2 = Thread(target=func2)
    t2.start()
    print('主线程')
# 主线程
# hello2
#这里func被安排了守护线程,先执行了主线程,然后打印非守护线程,最后守护线程sleep 了 3s没等结束 整个进程就结束了
#线程是否也会抢占资源?
from threading import Thread
import time
def func():
    global n
    temp = n
    time.sleep(0.001) #这里sleep的时候 100个线程已经开始了,每个线程里 temp取到的值都是100,线程的开启很快,如果这里写成了0.001s ,结果变成95
    n = temp - 1 #最后对n做了100次的赋值,赋值成了99
if __name__ == '__main__':
    n = 100
    t_list = []
    for i in range(100):
        t = Thread(target=func)
        t_list.append(t)
        t.start()
    for t in t_list:
        t.join()
    print(n) #99
#结果居然是99,n被所有线程抢占了
#线程的加锁
from threading import Thread,Lock
import time
def func(lock):
    time.sleep(1)
    with lock:
        global n
        temp = n
        n = temp - 1
if __name__ == '__main__':
    time1 = time.time()
    lock = Lock()
    n = 100
    t_list = []
    for i in range(100):
        t = Thread(target=func,args=(lock,))
        t_list.append(t)
        t.start()
    for t in t_list:
        t.join()
    time2 = time.time()
    print(time2-time1,n) #0.060001373291015625 0
    # 原来的并发执行,变成串行,牺牲执行效率保证数据安全
#如果每次开启一个线程t 都把它join一下,也是加锁的效果,但是结果
from threading import Thread,Lock
import time
def func(lock):
    time.sleep(1)
    with lock:
        global n
        temp = n
        n = temp - 1
if __name__ == '__main__':
    time1 = time.time()
    lock = Lock()
    n = 100
    t_list = []
    for i in range(100):
        t = Thread(target=func,args=(lock,))
        t_list.append(t)
        t.start()
        t.join()
    time2 = time.time()
    print(time2-time1,n) #100.91230297088623 0
    #结果过了100s才打印出结果0,加锁有技巧,在各个线程可能出现抢占资源的代码处加锁,其他代码并行执行,缩短时间
#线程死锁
from threading import Lock as Lock
import time
mutexA=Lock()
mutexA.acquire()
mutexA.acquire()
print(123)
mutexA.release()
mutexA.release()
# mutexA 连续请求加锁了2次,资源都是打印123?还没弄清楚

#递归锁 Rlock ,这样就可以打印了
from threading import RLock as Lock
import time
mutexA=Lock()
mutexA.acquire()
mutexA.acquire()
print(123)
mutexA.release()
mutexA.release()
#科学家吃面,死锁,不懂?
import time
from threading import Thread,Lock
noodle_lock = Lock()
fork_lock = Lock()
def eat1(name):
    noodle_lock.acquire()
    print('%s 抢到了面条'%name)
    fork_lock.acquire()
    print('%s 抢到了叉子'%name)
    print('%s 吃面'%name)
    fork_lock.release()
    noodle_lock.release()

def eat2(name):
    fork_lock.acquire()
    print('%s 抢到了叉子' % name)
    time.sleep(1)
    noodle_lock.acquire()
    print('%s 抢到了面条' % name)
    print('%s 吃面' % name)
    noodle_lock.release()
    fork_lock.release()

for name in ['哪吒','egon','yuan']:
    t1 = Thread(target=eat1,args=(name,))
    t2 = Thread(target=eat2,args=(name,))
    t1.start()
    t2.start()
#单例模式,大型翻车现场
import time
class singleton:
    __instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            time.sleep(0.000001) #这里sleep了一段时间,模拟时间片到了
            cls.__instance = super().__new__(cls)
        return cls.__instance
def func():
    a = singleton()
    print(a) #打印对象结果
from threading import Thread
if __name__ == '__main__':
    for i in range(10):
        t = Thread(target=func)
        t.start()
# <__main__.singleton object at 0x000001EDD08EA640>
# <__main__.singleton object at 0x000001EDD06AF340>
# <__main__.singleton object at 0x000001EDD06AF340>
# ....
#这里显示了两个不同的对象地址,说明不是单例了,单例模式也不安全了
#单例模式,加锁,外部传进来
class singleton:
    __instance = None
    def __new__(cls, *args, **kwargs):
        with args[0]:
            if not cls.__instance:
                cls.__instance = super().__new__(cls)
        return cls.__instance
def func(lock):
    a = singleton(lock)
    print(a)
from threading import Thread,Lock
if __name__ == '__main__':
    lock = Lock()
    for i in range(10):
        t = Thread(target=func,args=(lock,))
        t.start()
# <__main__.singleton object at 0x0000026C4200C730>
# <__main__.singleton object at 0x0000026C4200C730>
# <__main__.singleton object at 0x0000026C4200C730>
# 。。。
# 这样虽然能解决,但是传递了参数到单例类中,面向对象中能封装到类中的就可以不用参数传递
#单例模式,在单例对象中加锁
class singleton:
    from threading import Lock
    __instance = None
    lock = Lock()
    def __new__(cls, *args, **kwargs):
        with cls.lock:
            if not cls.__instance:
                cls.__instance = super().__new__(cls)
        return cls.__instance
def func():
    a = singleton()
    print(a)
from threading import Thread
if __name__ == '__main__':
    for i in range(10):
        t = Thread(target=func)
        t.start()
# <__main__.singleton object at 0x000002A1EFF6B790>
# <__main__.singleton object at 0x000002A1EFF6B790>
# <__main__.singleton object at 0x000002A1EFF6B790>
# ......
#【记住】
#不操作全局变量,几乎不会出现线程安全问题,包括类里的静态变量
# +=  -=  *=  /=  if  while  a=a.strip() split() 等数据不安全
# queue logging  数据安全
#dis 模块
import dis
def func():
    a = 1
    print(a)
print(dis.dis(func))
#显示该函数底层的实现
#递归锁RLock
#互斥锁只拿到一个钥匙,然后进去执行代码
#递归锁可以多次的拿钥匙,执行代码然后再挨个退出
#递归锁效率低
#互斥锁
from threading import Thread,Lock
def func(i,lock):
    lock.acquire()
    lock.acquire()
    print(i)
    lock.release()
    lock.release()

if __name__ == '__main__':
    lock = Lock()
    for i in range(6):
        t = Thread(target=func,args=(i,lock))
        t.start()
#这里会停住,lock.acquire()上了2次锁,没有结果,就执行不下去了
#递归锁
from threading import Thread,RLock
def func(i,lock):
    lock.acquire()
    lock.acquire()
    print(i)
    lock.release()
    lock.release()

if __name__ == '__main__':
    lock = RLock()
    for i in range(6):
        t = Thread(target=func,args=(i,lock))
        t.start()
#执行下去了,第一次 acquire 获得一次操作资源的权限,操作的是acquire 和最后一个release方法之间的代码(资源)
#层层执行,最后层层释放
posted on 2020-08-17 18:18  94小渣渣  阅读(144)  评论(0编辑  收藏  举报