标签:数据 环境变量 too 描述符 before 配置 read 安全 link
线程是操作系统能够运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
从技术性上来说,一段上下文(就是一个线程)由若干CPU寄存器的值组成,
进程与线程不同,一条线程是一段指令上下文。一个进程是一堆与计算有关的资源集合。一个进程可以有一条或多条线程。
注意:与进程有关的资源集合包含内存空间(一个进程中的所有线程共享同一块内存空间),文件描述符(例如:打开的socket链接)和安全认证(如:启动进程的用户的ID)。
进程
一个程序的一个执行实例被称为一个进程。
每个进程提供执行一个程序所需的资源。
一个进程有一个虚拟地址空间,可执行的代码,对操作系统对象开放的接口(句柄),安全认证上下文,一个唯一的进程标识符(PID),环境变量,优先级类,最小与最大的指定的工作空间以及最少执行的一条线程。
每一个进程伴随着一条线程启动,通常被称为主线程,主线程可以通过任何其他线程创建额外的线程。
进程与线程的区别
线程共享一个进程的地址(内存)空间,而进程拥有独立的内存空间。
线程可以直接连接到进程的数据段,而进程则拥有独立的父进程的数据段副本。
同一个进程的线程之间可以直接交流;而多个进程则需要一个中间进程来实现通信。
创建一个新线程很容易;而创建新进程则需要对其父进程进行复制。
线程可以对同一进程里的其他线程进行控制;进程则只能对其子进程进行控制。
对主要线程的改动(取消,优先级变动等)会影响进程中的其他线程的运行;而父进程的改动不会影响子进程。
示例
import threading
import time
def run(n):
print(‘task:‘, n)
before_sleep = time.time()
time.sleep(2)
after_sleep = time.time()
print(after_sleep - before_sleep)
t1 = threading.Thread(target=run, args=(‘t1‘, )) #args参数为元组,所以必须加逗号
t2 = threading.Thread(target=run, args=(‘t2‘, ))
t1.start()
t2.start()结果
task: t1 task: t2 2.021209478378296 2.021209478378296
看,如果是串行,2个线程应该睡4秒,但这里睡了2秒,成功!
下面是基于类的写法,效果是一样的
import threading
import time
class MyThread(threading.Thread):
def __init__(self, n):
super(MyThread, self).__init__()
self.n = n
def run(self):
print(‘task: ‘, self.n)
before_sleep = time.time()
time.sleep(2)
after_sleep = time.time()
print(after_sleep - before_sleep)
t1 = MyThread(‘t1‘)
t2 = MyThread(‘t2‘)
t1.start()
t2.start()结果
task: t1 task: t2 2.0057871341705322 2.0057871341705322
这种方式不常用,知道就行。
下面是一个继承式多线程的示例,同时启动50个线程,完毕后统一时间
import threading
import time
def run(n):
print(‘task: ‘, n)
time.sleep(2)
start_time = time.time()
t_l = [] #存放线程
for i in range(50):
t = threading.Thread(target=run, args=(‘t-%s‘ % i, ))
t.start()
t_l.append(t) #为了不阻塞其他线程的启动,先放在列表里,最后join
for t in t_l: #循环线程列表,执行所有线程
t.join()
print(‘All threads have ran down!‘)
print(‘Total cost: ‘, time.time() - start_time)结果
... ... ... task: t-44 task: t-45 task: t-46 task: t-47 task: t-48 task: t-49 All threads have ran down! Total cost: 2.021458387374878
在创建新线程时,子线程会从其父线程继承其线程属性,主线程是普通的非守护线程,默认情况下,它所创建的任何线程都是非守护线程。
在默认情况下,新线程通常会生成非守护线程或普通线程,如果新线程在运行,主线程将永远等待,无法正常退出。
主线程执行完毕并且没有任何非守护线程继续运行时,主线程可以正常终止退出了。
注意:
示例
import threading
import time
start_time = time.time()
def run(n):
print(‘task: ‘, n)
time.sleep(2)
print(‘Daemon thread cost: ‘, time.time() - start_time)
t_l = [] #存放线程
for i in range(10):
t = threading.Thread(target=run, args=(‘t-%s‘ % i, ))
t.setDaemon(True) #将当前线程设置为守护线程,daemon希腊神话中的半人半神精灵
t.start()
t_l.append(t) #为了不阻塞其他线程的启动,先放在列表里,最后join
# for t in t_l: #循环线程列表,执行所有线程
# t.join()
print(‘All threads have ran down!‘)
print(‘Primary thread cost: ‘, time.time() - start_time)2个结果,分别是
t.setDaemon(True)
task: t-0 task: t-1 task: t-2 task: t-3 task: t-4 task: t-5 task: t-6 task: t-7 task: t-8 task: All threads have ran down! Primary thread cost: 0.0
t.setDaemon(False)
task: t-0 task: t-1 task: t-2 task: t-3 task: t-4 task: t-5 task: t-6 task: t-7 task: t-8 task: All threads have ran down! t-9 Primary thread cost: 0.0 Daemon thread cost: Daemon thread cost: Daemon thread cost: 2.005704402923584 2.005704402923584 Daemon thread cost: Daemon thread cost: 2.005704402923584 Daemon thread cost: 2.005704402923584 2.005704402923584 Daemon thread cost: 2.005704402923584 2.005704402923584 Daemon thread cost: Daemon thread cost: Daemon thread cost: 2.005704402923584 2.005704402923584 2.005704402923584
可以看到,当子线程设置为守护线程时,主线程并没有理会子线程是否结束(没有执行sleep(2)语句)就已经结束了。当子线程为非守护线程时,主线程等待子线程执行完毕才结束。
标签:数据 环境变量 too 描述符 before 配置 read 安全 link
原文地址:https://www.cnblogs.com/infinitecodes/p/12114461.html