线程进阶

Posted dymlnet

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程进阶相关的知识,希望对你有一定的参考价值。

在了解进程之后,我们可以做一个多线程的聊天室

服务端

import socket
from multiprocessing import Process

def talk(conn):
    conn.send(bconnected)
    ret = conn.recv(1024)
    print(ret)

if __name__ == __main__:
    sk = socket.socket()
    sk.bind((127.0.0.1, 8080))
    sk.listen()
    while True:
        conn,addr = sk.accept()
        p = Process(target=talk,args=(conn,))
        p.start()
    conn.close()
    sk.close()

客户端

import socket
sk = socket.socket()
sk.connect((127.0.0.1,8080))
ret = sk.recv(1024)
print(ret)
msg = input(>>>)
sk.send(msg.encode(utf-8))
sk.close()

我们不论建立几个客户端都可以做到和服务端互动,他们每一个都是自己独立的线程

 

守护进程  子进程会在主进程结束时结束

# start  开启一个进程
# join   用join可以让主进程等待子进程结束

# 守护进程
# 守护进程会随着主进程的代码执行结束而结束
# 正常的子进程没有执行完的时候主进程要一直等着
import time
from multiprocessing import Process
def func():
    print(--*10)
    time.sleep(15)
    print(--*10)

def cal_time():
    while True:
        time.sleep(1)
        print(过去了1秒)

if __name__ == __main__:
    p = Process(target=cal_time)
    p.daemon = True     # 一定在开启进程之前设置
    p.start()
    p2 = Process(target=func)  # 15s
    p2.start()
    for i in range(100):    # 10s
        time.sleep(0.1)
        print(**i)
    p2.join()

# 守护进程的进程的作用:
    # 会随着主进程的代码执行结束而结束,不会等待其他子进程
# 守护进程 要在start之前设置
# 守护进程中 不能再开启子进程

 

进程的其他方法

import time
from multiprocessing import Process
# def func():
#     print(‘wahaha‘)
#     time.sleep(5)
#     print(‘qqxing‘)
# if __name__ == ‘__main__‘:
#     p = Process(target=func)
#     p.start()
#     print(p.is_alive())  #
#     time.sleep(0.1)
#     p.terminate()        # 关闭进程  异步
#     print(p.is_alive())  # ???
#     time.sleep(1)
#     print(p.is_alive())
# p.is_alive()   # 是否活着 True代表进程还在 False代表进程不在了
# p.terminate()  # 结束一个进程,但是这个进程不会立刻被杀死


# 属性
# pid   查看这个进程 进程id
# name  查看这个进程的名字

# def func():
#     print(‘wahaha‘)
#     time.sleep(5)
#     print(‘qqxing‘)
# if __name__ == ‘__main__‘:
#     p = Process(target=func)
#     p.start()
#     print(p.name,p.pid)
#     p.name = ‘哇哈哈哈‘
#     print(p.name)

# class MyProcess(Process):
#     def run(self):
#         print(‘wahaha‘,self.name,self.pid)
#         time.sleep(5)
#         print(‘qqxing‘,self.name,self.pid)
# if __name__ == ‘__main__‘:
#     p = MyProcess()
#     p.start()
#     print(p.pid)

# 进程中的其他方法
# 守护进程 p.daemon = True
# 两个方法 p.is_alive() p.terminate()
# 两个属性 p.pid p.name

 

 

锁  在一个主线程开启多个子线程时,这几个子线程的数据是隔离的,但是当他们都与主进程互动时,难免会产生数据混乱,这种情况我们叫做

数据不安全,解决办法就是在进程中加锁

# from multiprocessing import Lock
# lock = Lock()
# lock.acquire()  # 需要锁   拿钥匙
# lock.acquire()  # 需要锁   阻塞
#
# lock.release()  # 释放锁  还钥匙

# 锁 就是在并发编程中 保证数据安全

# 多进程 实现 并发

import json
import time
import random
from multiprocessing import Lock
from multiprocessing import Process

def search(i):
    with open(ticket) as f:
        print(i,json.load(f)[count])

def get(i):
    with open(ticket) as f:
        ticket_num = json.load(f)[count]
    time.sleep(random.random())
    if ticket_num > 0:
        with open(ticket,w) as f:
            json.dump({count:ticket_num-1},f)
        print(%s买到票了%i)
    else:
        print(%s没票了%i)

def task(i,lock):
    search(i)   # 查看票
    lock.acquire()
    get(i)      # 抢票
    lock.release()

if __name__ == __main__:
    lock = Lock()
    for i in range(20):  # 20个人同时抢票
        p = Process(target=task,args=(i,lock))
        p.start()

 

当我们需要同时几个进程的时候,就相当于多给几个钥匙,这种情况叫信号量

# 信号量
from multiprocessing import Semaphore
# sem = Semaphore(4)
# sem.acquire()  # 需要钥匙
# print(0)
# sem.acquire()  # 需要钥匙
# print(1)
# sem.acquire()  # 需要钥匙
# print(2)
# sem.acquire()  # 需要钥匙
# print(3)
# sem.release()
# sem.acquire()  # 需要钥匙
# print(4)
import time
import random
from multiprocessing import Semaphore
from multiprocessing import Process
def sing(i,sem):
    sem.acquire()
    print(%s : 进入 ktv%i)
    time.sleep(random.randint(1,10))
    print(%s : 出 ktv%i)
    sem.release()
# 迷你唱吧  20个人,同一时间只能有4个人进去唱歌
if __name__ == __main__:
    sem = Semaphore(4)
    for i in range(20):
        Process(target=sing,args=(i,sem)).start()

 

event模块

可以控制进程的阻塞

# 事件
# 所有的阻塞 都是同步
# recv accept input sleep
# 阻塞多个进程  异步阻塞
# lock 10进程
# 事件 —— 异步阻塞
# 事件 标志 同时 是所有的进程 都陷入阻塞

from multiprocessing import Event   #事件
# e = Event() # 实例化一个事件  标志/交通信号灯
# e.set()     # 将标志变成非阻塞/交通灯变绿
# e.wait()    # 刚实例化出来的一个事件对象,默认的信号是阻塞信号/默认是红灯
#             # 执行到wait,要先看灯,绿灯行红灯停,如果在停的过程中灯绿了,
#             # 就变成非阻塞了
# e.clear()   # 将标志又变成阻塞/交通灯变红
#
# e.is_set() # 是否阻塞 True就是绿灯 False就是红灯

# 红绿灯

import time
import random
from multiprocessing import Process
from multiprocessing import Event
def traffic_light(e):
    while True:
        if e.is_set():
            time.sleep(3)
            print(红灯亮)
            e.clear()      # 绿变红
        else:
            time.sleep(3)
            print(绿灯亮)
            e.set()        # 红变绿

def car(i,e):
    e.wait()
    print(%s车通过%i)

if __name__ == __main__:
    e = Event()   # 立一个红灯
    tra = Process(target=traffic_light,args=(e,))
    tra.start()   # 启动一个进程来控制红绿灯
    for i in range(100):
        if i%6 == 0 :
            time.sleep(random.randint(1,3))
        car_pro = Process(target=car, args=(i,e))
        car_pro.start()

当我们想要在几个子进程间调用数据时,使用队列方法

# 进程之间的通信

# lock
# 1 lock.acquire
# 2 lock.acquire

# sem

# e


# ‘hello‘  --> 子进程
# 子进程1 ‘hello’ --> 子进程2

from multiprocessing import Queue
# q = Queue(3)
# q.put(1)
# q.put(2)
# q.put(3)
# q.put(4)
#
# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get())  # 如果队列里已经没有值了 就会阻塞等待有一个值

#1.进程之间通信 可以使用multiprocessing 的 Queue模块
#2.队列有两种创建方式 第一种不传参数 这个队列就没有长度限制 ;传参数,创建一个有最大长度限制的队列
#3.提供两个重要方法;put get
#4.qsize

from multiprocessing import Process
from multiprocessing import Queue

# def q_put(q):
#     q.put(‘hello‘)
#
# def q_get(q):
#     print(q.get())
#
# if __name__ ==‘__main__‘:
#     q = Queue()
#     p = Process(target=q_put,args=(q,))
#     p.start()
#     p1 = Process(target=q_get, args=(q,))
#     p1.start()


# 通过队列实现了 主进程与子进程的通信   子进程与子进程之间的通信
# 生产者消费者模型

# 我要生产一个数据 然后 给一个函数 让这个函数依赖这个数据进行运算  拿到结果  —— 同步过程

# 做包子 和 吃包子
import time
def producer(q):  # 生产者
    for i in  range(100):
        q.put(包子%s%i)

def consumer(q): #  消费者
    for i in range(100):
        time.sleep(1)
        print(q.get())

if __name__ == __main__:
    q = Queue(10)   # 托盘
    p = Process(target=producer,args=(q,))
    p.start()
    c1 = Process(target=consumer, args=(q,))
    c2 = Process(target=consumer, args=(q,))
    c1.start()
    c2.start()

# 首先 对于内存空间来说 每次只有很少的数据会在内存中
# 对于生产与消费之间的不平衡来说
    # 增加消费者或者增加生产者来调节效率

 

以上是关于线程进阶的主要内容,如果未能解决你的问题,请参考以下文章

Atom编辑器入门到精通 Atom使用进阶

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段

iOS进阶学习-多线程

我的Android进阶之旅关于Android平台获取文件的mime类型:为啥不传小写后缀名就获取不到mimeType?为啥android 4.4系统获取不到webp格式的mimeType呢?(代码片段

我的Android进阶之旅关于Android平台获取文件的mime类型:为啥不传小写后缀名就获取不到mimeType?为啥android 4.4系统获取不到webp格式的mimeType呢?(代码片段