day19-总结

"""author = Zard"""
import threading
from time import sleep
from datetime import datetime

主线程和子线程

默认情况下,进程有一个线程,这个线程叫主线程 -- 主线程是系统自动创建的
默认所有的代码都是在主线程中执行

程序猿通过代码创建的线程都叫子线程

创建子线程

python中内置的threading模块中提供了和线程操作相关的类和方法

threading模块中有个Thread类,这个类或者这个的子类的对象就是线程对象;
需要子线程的时候就创建Thread类的对象

def download(name):
  print(' %s 开始下载:%s ' % (datetime.now(),name))
  print(threading.current_thread())     # 查看当前执行的线程
  sleep(5)
  print(' %s 下载结束:%s ' % (datetime.now(),name))

if __name__ == '__main__':
  # download('龙猫')
  # download('你的名字')

创建线程对象

1)语法
Thread(target=函数,args=实参列表)    --  返回子线程对象
2)说明
target  -   必须要赋一个函数,这个函数会在子线程中调用
args    -   赋一个元组,元组中的元素就是调用target函数的时候需要传的参数

创建2个子线程

t1 = threading.Thread(target=download,args=('龙猫',))
t2 = threading.Thread(target=download,args=('你的名字',))

2.让子线程开始执行

线程对象,start() -- 在子线程中调用target对应download,并且将args中的值作为实参
t1.start()
t2.start()

程序的结束(进程的结束)

一个进程是否结束,看是否这个进程中的每个线程都结束
线程结束:任务执行完成,遇到exit(),发生异常(只针对发生的线程)
线程中遇到exit(),线程直接结束
程序出现异常只会影响一个线程

from threading import *
from time import sleep
from datetime import datetime

推荐使用,类似于面向对象的方式

通过创建Thread类的子类对象来创建 子线程

1)声明一个类继承Thread

class DownloadThread(Thread):

    def __init__(self,name):
        super().__init__()
        self.name = name

2)实现run方法,这个方法中的代码就是会在子线程中执行的代码

def run(self) -> None:
      print(' %s 开始下载:%s ' % (datetime.now(),self.name))
      print(current_thread())  # 查看当前执行的线程
      sleep(5)
      print(' %s 下载结束:%s ' % (datetime.now(), self.name))


if __name__ == '__main__':
  # 3)创建子类的线程对象
  t1 = DownloadThread('你是魔鬼吗?')

  # 4)通过start去执行子线程中的任务
  t1.start()

  t2 = DownloadThread('程序猿猝死案例集锦')
  t2.start()

练习:用套接字实现,一个服务器同时处理多个客户端的功能(一个server可以同时和多个人进行聊天)

from socket import *
from threading import *
# 创建多线程
class Chat(Thread):
    def __init__(self,connection,address):
        super().__init__()
        self.connection = connection
        self.address = address

    def run(self) -> None:
        while True:
            re_message = self.connection.recv(1024).decode(encoding='utf-8')
            print(self.address,re_message)

            message = '你是**吗?'
            self.connection.send(message.encode())

创建服务器对象

server = socket()
# 绑定ip地址
server.bind(('10.7.160.56',8888))
# 开始监听
server.listen(100)
# 服务器不断运行
print('开始监听...')
while True:

    connection,address = server.accept()
    print('有新用户!')
    t1 = Chat(connection,address)
    t1.start()

from threading import *
from datetime import *
from time import *
from random import randint

class Download(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name


    def run(self) -> None:
        print('%s  - 开始下载 %s'%(datetime.now(),self.name))
        t = randint(2,6)
        sleep(t)
        print('%s  - 下载完成 %s'%(datetime.now(),self.name))


if __name__ == '__main__':
    print('=========================无忧==========================')
    t1 = Download('素人初摄.avi')
    t2 = Download('丧心病款.avi')
    t3 = Download('夜蒲团子.mp4')
    t2.start()
    t1.start()
    t3.start()

join的使用

线程对象.join()
其他的代码

这儿的其他的代码会等到指定的线程对象结束后才会执行

t1.join()
t2.join()
t3.join()

from threading import Thread,Lock,RLock
from time import sleep

怎么加锁

1)保证一个数据对应一把锁:创建锁对象
2)使用数据前加锁:锁对象.acquire()
3)保证数据使用完成后释放锁:锁对象.release()

 数据
account = 1000
 1.创建锁对象
lock = Lock()


def save_money(num):
    # 2.加锁
    lock.acquire()

    print('开始存钱')
    global account
    balance = account
    sleep(4)
    account = balance + num
    # 3.释放锁
    lock.release()
    print('余额:%d'% account)

def draw_money(num):
    print('开始取钱')
    # 2.加锁
    lock.acquire()
    global account
    balance = account
    if balance < 0:
        print('余额不足')
        return
    sleep(4)


    account = balance - num
    print('余额:%d'% account)
    # 3.释放锁
    lock.release()

t1 = Thread(target=save_money,args=(1000,))
t2 = Thread(target=draw_money,args=(500,))

t1.start()
t2.start()

你可能感兴趣的:(day19-总结)