python_多任务编程

多任务

多任务:在同一时间内执行多个任务
多任务的目的:多任务的最大好处是充分利用CPU资源,提高程序的执行效率
并发:在一段时间内交替执行多个任务
并行:在同一时刻同时执行多个任务

多进程(多任务的实现方式)

进程:<kbd>运行</kbd>中的程序,分配资源的最小单位
线程:使用资源的最小单位
进程和线程的关系:一个程序运行后至少有一个进程,每个进程默认有一个线程

多进程的使用流程:

  1. 导入进程模块(multiprocessing)

    import multiprocessing     
    
  2. 创建子进程对象

     sub_process = multiprocessing.Process(group=None, target=None, name=None, args, kwargs)
     # 其中:args 方式传参应注意参数顺序一致,kwargs 传参应注意字典的 key 与参数名一致
    
  3. 启动子进程

     sub_process.start() #启动子进程
     sub_process.join() # 进程等待
     sub_process.terminate() # 终止子进程
     multiprocessing.current_process() #查看当前进程
     os.getpid() # 查看进程编号
     os.getppid() # 查看父进程编号
     os.kill(进程编号,9) # 根据进程编号强制杀死进程
     print(a, b, c) # 可以直接打印变量 a b c
    
     # 进程的运行是无序的,不依赖代码的先后顺序
    

实例:

# 单进程
import time


def dance():
    for i in range(5):
        time.sleep(1)
        print("DANCE", i)


def sing():
    for i in range(5):
        time.sleep(1)
        print("SING", i)


if __name__ == '__main__':
    dance()
    sing()

[运行结果]
[Done] exited with code=0 in 10.052 seconds

# 多进程
import time

# 导入进程模块
import multiprocessing


def dance():
    for i in range(5):
        time.sleep(1)
        print("DANCE", i)


def sing():
    for i in range(5):
        time.sleep(1)
        print("SING", i)


if __name__ == '__main__':
    # 创建子进程
    my_dance = multiprocessing.Process(target=dance)
    my_sing = multiprocessing.Process(target=sing)

    # 启动子进程
    my_dance.start()
    my_sing.start()

[运行结果]
[Done] exited with code=0 in 5.095 seconds

进程ID(os模块)

目的: 知道子进程是由哪个主进程创建的(子进程需要主进程回收资源)
os.getpid(): 表示获取当前进程编号
os.getppid(): 表示获取当前父进程编号

进程名字

  1. 进程起名字

     my_dance = multiprocessing.Process(target=dance, name="my_ProcessName")
    
  2. 获取进程的名字

     multiprocessing.current_process()
    
     # 运行结果
     <Process name='my_ProcessName' parent=151225 started>
    

进程参数

带有参数的函数:
args: 元组!!!(单个元素的元组有 , )
my_dance = multiprocessing.Process(target=dance, args=(5,))
    
kwargs: 字典!!!(key值要和函数中的形参完全重名)
my_dance = multiprocessing.Process(target=dance, kwargs={"count": 5})

进程之间不共享全局变量

进程之间不共享全局变量,是因为操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已

import multiprocessing
import time

# 全局变量列表
g_num = []

def my_write(): # 向全局变量g_num里写入数据
    global g_num
    for i in range(5):
        g_num.append(i)
    print("my_write:", g_num)


def my_read(): #读取全局变量g_num的值
    global g_num
    print("my_read:", g_num)


if __name__ == '__main__':
    sub_write = multiprocessing.Process(target=my_write)
    sub_read = multiprocessing.Process(target=my_read)

    sub_write.start()
    time.sleep(1) # 保证数据写入g_num中
    sub_read.start()

[运行结果]
my_write: [0, 1, 2, 3, 4]
my_read: []

守护主进程or销毁子进程

为了保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁
设置守护主进程或销毁主进程的目的是主进程退出子进程销毁,不让主进程再等待子进程去执行

  • 设置守护主进程: 子进程对象.daemon = True
  • 销毁子进程: 子进程对象.terminate()

多线程(多任务的实现方式)

多线程使用流程

  1. 导入线程模块(threading)
  2. 创建子线程
  3. 开始子线程

实例

import time

# 导入线程模块
import threading


def dance():
    for i in range(5):
        time.sleep(1)
        print("DANCE", i)


def sing():
    for i in range(5):
        time.sleep(1)
        print("SING", i)


if __name__ == '__main__':
    # 创建子进程
    my_dance = threading.Thread(target=dance)
    my_sing = threading.Thread(target=sing)

    # 启动子进程
    my_dance.start()
    my_sing.start()

[运行结果]
[Done] exited with code=0 in 5.042 seconds

线程之间是无序执行的

守护主线程

主线程会等待子线程的结束而结束
设置守护主线程的两种方式:

  • threading.Thread(target=show_info, daemon=True)
  • 线程对象.setDaemon(True)

线程参数(同进程)

线程之间共享全局变量

好处是可以对全局变量的数据进行共享
但是可能会导致数据出现错误问题

import threading
import time

g_num = []


def my_write():
    global g_num
    for i in range(5):
        g_num.append(i)
    print("my_write:", g_num)


def my_read():
    global g_num
    print("my_read:", g_num)


if __name__ == '__main__':
    sub_write = threading.Thread(target=my_write)
    sub_read = threading.Thread(target=my_read)

    sub_write.start()
    time.sleep(1)
    sub_read.start()

[运行结果]
my_write: [0, 1, 2, 3, 4]
my_read: [0, 1, 2, 3, 4]

线程之间共享全局变量的问题

线程同步: 保证同一时刻只能有一个线程去操作全局变量 同步: 就是协同步调,按预定的先后次序进行运行。
线程同步的方式:

  • 线程等待(join)

      first_thread.start()
      first_thread.join() # 等待线程first_thread执行完毕再继续向下进行
      second_thread.start()    
    
  • 互斥锁
    对共享数据进行锁定,保证同一时刻只能有一个线程去操作
    互斥锁的使用:

    • 创建锁:mutex = threading.Lock()
    • 上锁:mutex.acquire()
    • 释放锁:mutex.release()
      注意避免死锁,在合适位置释放锁
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容