首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python3 与 C# 并发编程之~ 线程篇1

Python3 与 C# 并发编程之~ 线程篇1

原创
作者头像
逸鹏
发布2018-09-07 08:37:05
4280
发布2018-09-07 08:37:05
举报
文章被收录于专栏:逸鹏说道逸鹏说道

2.线程篇

示例代码:https://github.com/lotapp/BaseCode/tree/master/python/5.concurrent/Thread

终于说道线程了,心酸啊,进程还有点东西下次接着聊,这周4天外出,所以注定发文少了 +_+

用过Java或者Net的重点都在线程这块,Python的重点其实在上篇,但线程自有其独到之处~比如资源共享(更轻量级)

这次采用循序渐进的方式讲解, 先使用,再深入,然后扩展,最后来个案例,呃.呃.呃.先这样计划~欢迎纠正错误

2.1.入门篇

官方文档:https://docs.python.org/3/library/threading.html

进程是由若干线程组成的(一个进程至少有一个线程)

2.1.1.线程案例

用法和 Process差不多,咱先看个案例: Thread(target=test,args=(i,))

import osfrom threading import Thread, current_thread def test(name):    # current_thread()返回当前线程的实例    thread_name = current_thread().name  # 获取线程名    print(f"[编号:{name}],ThreadName:{thread_name}\nPID:{os.getpid()},PPID:{os.getppid()}")def main():    t_list = [Thread(target=test, args=(i, )) for i in range(5)]    for t in t_list:        t.start() # 批量启动    for t in t_list:        t.join() # 批量回收    # 主线程    print(f"[Main]ThreadName:{current_thread().name}\nPID:{os.getpid()},PPID:{os.getppid()}")if __name__ == '__main__':    main()

输出:(同一个进程ID)

[编号:0],ThreadName:Thread-1PID:20533,PPID:19830[编号:1],ThreadName:Thread-2PID:20533,PPID:19830[编号:2],ThreadName:Thread-3PID:20533,PPID:19830[编号:3],ThreadName:Thread-4PID:20533,PPID:19830[编号:4],ThreadName:Thread-5PID:20533,PPID:19830[Main]ThreadName:MainThreadPID:22636,PPID:19830

注意一点:Python里面的线程是Posix Thread

2.1.2.指定线程名

如果想给线程设置一个Div的名字呢?:

from threading import Thread, current_threaddef test():    # current_thread()返回当前线程的实例    print(f"ThreadName:{current_thread().name}")def main():    t1 = Thread(target=test, name="小明")    t2 = Thread(target=test)    t1.start()    t2.start()    t1.join()    t2.join()    # 主线程    print(f"[Main],ThreadName:{current_thread().name}")if __name__ == '__main__':    main()

输出:(你指定有特点的名字,没指定就使用默认命令【联想古时候奴隶名字都是编号,主人赐名就有名了】)

ThreadName:小明ThreadName:Thread-1[Main],ThreadName:MainThread

类的方式创建线程

from threading import Threadclass MyThread(Thread):    def __init__(self, name):        # 设个坑,你可以自行研究下        super().__init__()  # 放在后面就报错了        self.name = name    def run(self):        print(self.name)def main():    t = MyThread(name="小明")    t.start()    t.join()if __name__ == '__main__':    main()

输出:(和Thread初始化的name冲突了【变量名得注意哦】)

小明

2.1.3.线程池案例

from multiprocessing.dummy import Pool as ThreadPool, current_processdef test(i):    # 本质调用了:threading.current_thread    print(f"[编号{i}]{current_process().name}")def main():    p = ThreadPool()    for i in range(5):        p.apply_async(test, args=(i, ))    p.close()    p.join()    print(f"{current_process().name}")if __name__ == '__main__':    main()

输出:

[编号0]Thread-3[编号1]Thread-4[编号3]Thread-2[编号2]Thread-1[编号4]Thread-3MainThread
微微扩展一下

对上面代码,项目里面一般都会这么优化:(并行这块线程后面会讲,不急)

from multiprocessing.dummy import Pool as ThreadPool, current_processdef test(i):    # 源码:current_process = threading.current_thread    print(f"[编号{i}]{current_process().name}")def main():    p = ThreadPool()    p.map_async(test, list(range(5)))    p.close()    p.join()    print(f"{current_process().name}")if __name__ == '__main__':    main()

输出:

[编号0]Thread-2[编号1]Thread-4[编号2]Thread-3[编号4]Thread-2[编号3]Thread-1MainThread

代码改动很小(循环换成了map)性能提升很明显(密集型操作)

2.1.4.其他扩展

Thread初始化参数:

  1. daemon:是否为后台线程(主进程退出后台线程就退出了)

Thread实例对象的方法:

  1. isAlive(): 返回线程是否活动的
  2. getName(): 返回线程名
  3. setName(): 设置线程名
  4. isDaemon():是否为后台线程
  5. setDaemon():设置后台线程

threading模块提供的一些方法:

  1. threading.currentThread(): 返回当前的线程实例
  2. threading.enumerate(): 返回一个包含正在运行的线程List(线程启动后、结束前)
  3. threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

看一个小案例:

import timefrom threading import Thread, active_countdef test1():    print("test1")    time.sleep(1)    print("test1 ok")def test2():    print("test2")    time.sleep(2)    print("test2 ok")def main():    t1 = Thread(target=test1)    t2 = Thread(target=test2, daemon=True)    t1.start()    t2.start()    t1.join()    print(active_count())    print(t1.is_alive)    print(t2.is_alive)    # t2.join() # 除非加这一句才等daemon线程,不然直接不管了if __name__ == '__main__':    main()

下次就以 multiprocessing.dummy模块为例了,API和 threading几乎一样,进行了一些并发的封装,性价比更高

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2.线程篇
    • 2.1.入门篇
      • 2.1.1.线程案例
      • 2.1.2.指定线程名
      • 2.1.3.线程池案例
      • 2.1.4.其他扩展
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档