python学习-并发编程(十四)

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
原文地址:https://www.cnblogs.com/wang-mengmeng/p/11650731.html