14.2线程的创建与启动

import threading

# 定义一个普通的action函数,该函数准备作为线程执行体
def action(max):
for i in range(max):
print(threading.current_thread().getName() + " " + str(i)) # 下面是主程序(也就是主线程的执行体)
for i in range(100):
print(threading.current_thread().getName() + " " + str(i))
if i == 20:
# 创建并启动第一个线程
t1 = threading.Thread(target=action, args=(100,))
t1.start()
# 创建并启动第二个线程
t2 = threading.Thread(target=action, args=(100,))
t2.start()
print('主线程执行完成!') 输出结果:
...
Thread-2 83
MainThread 99
Thread-1 81
Thread-2 84
主线程执行完成!
Thread-1 82
Thread-2 85
Thread-1 83
...

first_thread

当python程序开始运行后,程序至少会创建一个主线程,主线程的线程执行体就是程序中的主程序-没有放在任何函数中的代码。

以上程序共包含三个线程,这三个线程的执行没有先后顺序,它们以并发方式执行:Thread-1执行一段时间,然后Thread-2或MainThread获得cpu执行一段时间,接下来又换其他线程执行,这就是典型的线程并发执行-cpu以快速轮换的方式在多个线程之间切换,从而给用户一种错觉:多个线程似乎同时在执行。

简言之,多线程就是让多个函数能并发执行,让普通用户感觉到多个函数似乎同时在执行。

在默认情况下 , 主线程的名字为 MainThread , 用户 启动的 多 个线程的名 字依次为 Thread-1 、 Thread-2, Thread-3

14.3线程的生命周期

14.4控制线程

import threading

def action(max):
for i in range(max):
print(threading.current_thread().name + "" + str(i)) threading.Thread(target=action, args=(100,), name="新线程").start() for i in range(100):
if i == 20:
jt = threading.Thread(target=action, args=(100,), name="被join的线程")
jt.start()
jt.join()
print(threading.current_thread().name + "" + str(i)) 输出结果:
...
MainThread19
新线程20
新线程21
新线程22
新线程23
被join的线程0
新线程24
被join的线程1
...

join_thread

主线程执行到 i==20 时,程序启动“被join的线程”,所以主线程将一直处于阻塞状态,直到“被join的线程”执行完成。

import threading

def action(max):
for i in range(max):
print(threading.current_thread().name + "" + str(i))
t = threading.Thread(target=action,args=(100,),name="后台进程")
t.daemon = True # 必须在start()前设置
t.start()
for i in range(10):
print(threading.current_thread().name + "" + str(i)) 输出结果:
后台进程0
MainThread0
后台进程1
MainThread1
后台进程2
MainThread2
后台进程3
MainThread3
MainThread4
后台进程4
MainThread5
后台进程5
MainThread6
后台进程6
MainThread7
后台进程7
MainThread8
后台进程8
MainThread9
后台进程9

daemon_thread(后台进程或守护进程)

如果所有前台线程死亡,那么后台线程会自动死亡。

import time

for i in range(4):
print("当前时间:%s" % time.ctime())
time.sleep(1) # 调用sleep()函数让线程暂停1s 输出结果:
当前时间:Thu Oct 10 22:34:24 2019
当前时间:Thu Oct 10 22:34:25 2019
当前时间:Thu Oct 10 22:34:26 2019
当前时间:Thu Oct 10 22:34:27 2019

线程睡眠:sleep

14.5线程同步

14.6线程通信

14.7线程池

线程池在系统启动时即创建大量空闲的线程,程序只要将一个函数提交给线程池,线程池就会启动一个空闲的线程来执行它,当该函数执行结束后,该线程并不会死亡,而是再返回到线程池中变成空闲状态,等待执行下一个函数。

14.8线程相关类

定时器

from threading import Timer

def hello():
print("hello world!") t = Timer(10.0, hello) # 使用Timer控制10s后执行hello函数
t.start()

Timer1

from threading import Timer
import time # 定义总共输出几次的计数器
count = 0
def print_time():
print("当前时间:%s" % time.ctime())
global t, count
count += 1
# 如果count小于10,开始下一次调度
if count < 10:
t = Timer(1, print_time)
t.start()
# 指定1秒后执行print_time函数
t = Timer(1, print_time)
t.start() 输出结果:
当前时间:Thu Oct 10 23:11:09 2019
当前时间:Thu Oct 10 23:11:10 2019
当前时间:Thu Oct 10 23:11:11 2019
当前时间:Thu Oct 10 23:11:12 2019
当前时间:Thu Oct 10 23:11:13 2019
当前时间:Thu Oct 10 23:11:14 2019
当前时间:Thu Oct 10 23:11:15 2019
当前时间:Thu Oct 10 23:11:16 2019
当前时间:Thu Oct 10 23:11:17 2019
当前时间:Thu Oct 10 23:11:18 2019

Timer2

上面程序开始运行后,程序控制 l s 后执行 print_time()函数 。 print_time()函数中的粗体字代码
判断 : 如果 count 小于 10 ,程序再次使用 Timer 调度 ls 后执行 print_time()函数,这样就可以控制
print_time()函数多次重复执行

任务调度

import sched, time
import threading # 定义线程调度器
s = sched.scheduler() # 定义被调度的函数
def print_time(name='default'):
print("%s 的时间: %s" % (name, time.ctime()))
print('主线程:', time.ctime())
# 指定10秒之后执行print_time函数
s.enter(10, 1, print_time)
# 指定5秒之后执行print_time函数,优先级为2
s.enter(5, 2, print_time, argument=('位置参数',))
# 指定5秒之后执行print_time函数,优先级为1
s.enter(5, 1, print_time, kwargs={'name': '关键字参数'})
# 执行调度的任务
s.run()
print('主线程:', time.ctime()) 输出结果:
主线程: Thu Oct 10 23:18:27 2019
关键字参数 的时间: Thu Oct 10 23:18:32 2019
位置参数 的时间: Thu Oct 10 23:18:32 2019
default 的时间: Thu Oct 10 23:18:37 2019
主线程: Thu Oct 10 23:18:37 2019

sched

最新文章

  1. Nginx泛解析的匹配域名绑定到子目录配置
  2. 用webBrowser打开网页出现脚本错误怎么办
  3. JS代码实用代码实例(输入框监听,点击显示点击其他地方消失,文件本地预览上传)
  4. PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)
  5. Envelope Letter
  6. Effective C++ -----条款02:尽量以const, enum, inline替换 #define
  7. JAVA GUI之CardLayout
  8. 使用passenger在Centos7部署Puma+Nginx+Ruby on Rails
  9. ACE的Socket初步
  10. cocos2dX 事件之触摸事件和触摸事件集合
  11. typescript之初学习
  12. 让策划也能轻松修改数据的方法:运用Excel2Json2Object插件将xml表格转为Object导入脚本
  13. Codeforces | CF1010C 【Border】
  14. 使用Log4j日志处理
  15. leetcode-algorithms-34 Find First and Last Position of Element in Sorted Array
  16. Chrome 插件编写日记
  17. JVM 加载class文件的原理
  18. 第十一章 自己实现一致性hash算法
  19. 1221. [HNOI2001]软件开发【费用流】
  20. bzoj1511 [POI2006]OKR-Periods of Words kmp+乱搞

热门文章

  1. zookeeper 集群相关配置实践
  2. HTML定位和布局----float浮动
  3. 007:CSS字体图标
  4. 31 (OC)* 内存管理
  5. Vue学习之如何进行调试
  6. linux环境下Nginx的配置及使用
  7. 简述python的turtle绘画命令及解释
  8. # C# 中的Task创建指南
  9. 阿里云服务器CentOS6.9安装maven
  10. springboot 2.1.3 + mybatis + druid配置多数据源