美文网首页
2019-05-09多线程

2019-05-09多线程

作者: 十点半的橙汁 | 来源:发表于2019-05-13 22:03 被阅读0次

一、多线程

import time
from datetime import datetime
import threading   #专门提供和线程相关的操作

每一个进程都有一个线程,这个线程叫主线程;其他的线程都叫子线程

def download(film_name):
    print('开始下载: %s' % film_name, datetime.now())
    time.sleep(5)
    print('%s下载完成' % film_name, datetime.now())


# 在一个线程里面,下两个电影
# download('齐天大圣')
# download('007')

# 2、线程模块

# 1)current_thread函数  --  获取当前线程
print(threading.current_thread())

# 2)Thread类
'''
Thread类的对象就是线程,所有需要就创建这个类的对象。

Thread(target,*args,**kwargs) 
target  --  函数,需要在当前创建的子线程中调用的函数
args/kwargs  --  调用target中的函数需要的实参列表


'''
# a.创建线程对象
t1 = threading.Thread(target=download, args=('齐天大圣',) )
# t1 = threading.Thread(target=download,kwargs={'film_name':'齐天大圣')

t2 = threading.Thread(target=download, args=('007',) )

# b.开始执行子线程中的任务:线程对象.start()
# 通过start方法在子线程中去调用target对应的函数
t1.start()
t2.start()

二、自己重写Thread

# 1、创建自己的线程类:
'''
1)声明一个类,继承Thread
2)实现run方法,这个方法中的任务就是需要再子线程中执行的任务
'''


class DowLoadThread(Thread):
    def __init__(self,file_name):
        super().__init__()
        self.file_name = file_name

    def run(self):
        # print(current_thread())
        # print('在子线程中执行的代码')
        print('开始下载:%s' % self.file_name, datetime.now())
        time.sleep(4)
        print('结束下载: %s' % self.file_name, datetime.now())
    def p(self):
        print('kkkkkkkkkkkkkkkkkk')


# 3)用子类直接创建线程对象
t1 = DowLoadThread('红警')
t2 = DowLoadThread('坦克')

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

# t1.run()    # 不能直接调用run方法,因为这样调用不会在子线程中执行任务。这样调用就直接是在主线程中执行的。

# 注意:一个进程中如果有多个线程,程序会在所有线程都结束才结束。
#       发送异常崩溃其实崩溃的是线程。

三、如果希望某个任务是在某个线程结束后才执行,那就将这个任务的代码放在对应线程对象调用join方法的后面

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


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

    def run(self):
        print('开始下载:%s' % self.name, datetime.now())
        # time.sleep(randint(5, 10))
        time.sleep(self.time)
        print('下载结束:%s' % self.name, datetime.now())


t1 = DownLoadThread('龙珠GT', 7)
t2 = DownLoadThread('魂斗罗', 4)
t1.start()
t2.start()


# 1、join
'''
如果希望某个任务是在某个线程结束后才执行,
那就将这个任务的代码放在对应线程对象调用join方法的后面
'''
t1.join()
print('over')

四、多线程中防止数据错乱

1、问题:
当多个线程同时对一个数据进行读写操作,可能会出现一个线程刚把数据读出来,
还没把数据写进去,另一个线程进行读操作,而出现的数据安全问题。

2、解决 -- 加锁
1)保证每个数据对应一个锁对象
2)操作数据前加锁,数据操作完成后释放锁


# 锁的使用:
'''
1、问题:
当多个线程同时对一个数据进行读写操作,可能会出现一个线程刚把数据读出来,
还没把数据写进去,另一个线程进行读操作,而出现的数据安全问题。

2、解决  -- 加锁
1)保证每个数据对应一个锁对象
2)操作数据前加锁,数据操作完成后释放锁
'''


class Account:
    def __init__(self, name, tel, balance):
        self.name = name
        self.tel = tel
        self.balance = balance
        # 关联一个锁对象
        self.lock = Lock()

    def save_money(self, money):
        # 加锁
        self.lock.acquire()
        print('开始存钱')
        value = self.balance
        time.sleep(4)
        self.balance = value + money
        print('存钱成功:%.2f' % self.balance)
        # 释放锁
        self.lock.release()

    def draw_money(self, money):
        self.lock.acquire()
        print('开始取钱')
        value = self.balance
        time.sleep(5)
        if value < money:
            print('取钱失败,余额不足')
            return
        self.balance = value - money
        print('取钱成功:%.2f' % self.balance)
        self.lock.release()


acount = Account('H', '1880', 10000)


# 一个线程存钱
t1 = Thread(target=acount.save_money, args=(1000,))

t2 = Thread(target=acount.draw_money, args=(500,))

# t1.start()
# t2.start()
share_data = 1000
lock = Lock()


def add_data(value):
    lock.acquire()
    global share_data
    old_data = share_data
    time.sleep(3)
    share_data = value+old_data
    lock.release()

t3 = Thread(target=add_data,args=(200,))
t4 = Thread(target=add_data, args=(300,))

t3.start()
t4.start()

t3.join()
t4.join()
print(share_data)

相关文章

网友评论

      本文标题:2019-05-09多线程

      本文链接:https://www.haomeiwen.com/subject/mxcgoqtx.html