一 操作系统发展史介绍

参考链接:http://www.cnblogs.com/alex3714/articles/5230609.html

二 进程与线程

进程: 对各种资源管理的集合 就可以称为进程。进程要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等。比如qq就可以称为一个进程。进程 要操作cpu , 必须要先创建一个线程。

线程: 是操作系统最小的调度单位, 是一串指令的集合。

进程与线程的区别?

1.线程共享内存空间,进程的内存是独立的。
2.线程可以直接访问其进程的数据段,进程拥有自己父进程数据段的副本。
3.同一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现
4.创建新线程很简单,创建新进程需要对其父进程进行一次克隆
5.一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程
6.对主线程的更改(取消,优先级更改等)可能会影响进程的其他线程的行为,对父进程的更改不会影响子进程。

参考链接:http://www.cnblogs.com/alex3714/articles/5230609.html

三 线程语法

我们知道,IO操作不占用cpu,计算占用cpu。
python多线程不适合cpu密集操作型的任务,适合io操作密集型的任务。

线程有2种调用方式,如下:

直接调用

import threading
import time def runtask(n):
print("task",n)
time.sleep(2) # 普通调用,程序执行完需要4秒
# run("t1")
# run("t2") # 两个线程并发,程序执行完仅需要2秒
t1 = threading.Thread(target=runtask,args=("t1",))
t2 = threading.Thread(target=runtask,args=("t2",)) t1.start()
t2.start()

继承式调用

import threading
import time class MyThread(threading.Thread):
def __init__(self,n):
super(MyThread,self).__init__()
self.n = n def run(self):#注意此处函数名必须为run
print("task", self.n)
time.sleep(2) t1 = MyThread("t1")
t2 = MyThread("t2") t1.start()
t2.start()
import threading
import time def runtask(n):
print("task",n)
time.sleep() # 使用for循环同时启动50个线程
for i in range():
t = threading.Thread(target=runtask,args=("t%s" %i,))
t.start()

使用for循环同时启动50个线程

四 join

一个程序可以看做是一个主线程,当它启动子线程后,就不再管子线程了,此时子线程与主线程是并行的关系,同时进行。所以在主线程中无法测试子线程的运行速度,如下代码实例:

import threading
import time
def runtask(n):
print("task",n)
time.sleep() start_time = time.time()
t1 = threading.Thread(target=runtask,args=("t1",))
t2 = threading.Thread(target=runtask,args=("t2",)) t1.start()
t2.start() print(time.time()-start_time) # 输出:0.0

那么如果我一定要测试所有子线程运行的总时间怎么办呢?可以通过t.join()设置在主线程中等待子线程执行完成。join()的作用就是使子线程执行完毕后,主线程才继续往下走。

import threading
import time
def runtask(n):
print("task",n)
time.sleep() start_time = time.time()
t1 = threading.Thread(target=runtask,args=("t1",))
t2 = threading.Thread(target=runtask,args=("t2",)) t1.start()
t2.start() t1.join() #等待t1执行完成
t2.join() #等待t2执行完成 print(time.time()-start_time) # 输出:2.0011143684387207

计算2个线程执行完所需的时间

import threading
import time def runtask(n):
print("task",n)
time.sleep() t_objs = [] #存线程实例
start_time = time.time() for i in range():
t = threading.Thread(target=runtask,args=("t%s" %i,))
t.start()
t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 for t in t_objs: # 循环线程实例列表,等待所有线程执行完毕
t.join() print(time.time()-start_time) # 输出:2.006114959716797

计算50个线程执行完毕所需的时间

注意:一定要把所有线程都启动后,才能执行t.join()等待。如果启动完一个线程就等待,然后才启动下一个线程,那么2个线程就变成了串行,完全失去了并发的功能。举例:

import threading
import time
def runtask(n):
print("task",n)
time.sleep() start_time = time.time()
t1 = threading.Thread(target=runtask,args=("t1",))
t2 = threading.Thread(target=runtask,args=("t2",)) t1.start()
t1.join() t2.start()
t2.join() print(time.time()-start_time) # 输出:4.0002288818359375

如下示例,通过threading.active_count()可以查看当前活跃的线程个数,虽然启动了2个子线程,但其实一共有3个线程在运行。通过threading.current_thread()可以看出谁是主线程,谁是子线程。第一个启动的线程并不是主线程,主线程就是程序本身。

import threading
import time
def runtask(n):
print("task",n)
time.sleep()
print(threading.current_thread()) t1 = threading.Thread(target=runtask,args=("t1",))
t2 = threading.Thread(target=runtask,args=("t2",))
t1.start()
t2.start()
print(threading.current_thread())
print(threading.active_count())
####输出:
####task t1
####task t2
####<_MainThread(MainThread, started )>
####
####<Thread(Thread-, started )>
####<Thread(Thread-, started )>

五 守护线程

守护线程:一个主线程可以发起多个守护线程,这些守护线程都是为主线程服务的,一旦主线程挂了,守护线程随之挂掉。守护线程的用途有帮助主线程管理资源、打开文件、监听端口、监听一些新的链接、把垃圾资源回收等,它可以干很多事情,由主线程定义。

子线程和守护线程的区别

虽然在启动子线程后,主线程和子线程是同时运行,但是当主线程运行完后,它还是会等待所有子线程都运行完毕,程序才会退出。如下示例,可以明显感觉到主线程运行完后,程序又等待了2秒才退出。
可以在子线程start之前,通过t.setDaemon(True)将子线程设置为守护线程。此时再运行程序,你就会发现,主线程运行完成后,程序直接退出,没有等待子线程。

import threading
import time def runtask(n):
print("task",n)
time.sleep() for i in range():
t = threading.Thread(target=runtask,args=("t%s" %i,))
####将main线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,m线程也会退出,由m启动的其它子线程会同时退出,不管是否执行完任务
# t.setDaemon(True) #把当前线程设置为守护线程,
t.start() print("main thread finished")

守护线程

所以,主线程一旦创建了子线程,子线程就完全独立了,它的运行不会再受主线程的控制。而守护线程不同,它的运行依赖于主线程,一旦主线程执行完毕,守护线程随之终止。

守护线程的用途:比如说现在写一个socketserver,每有一个用户连接,你就为其分配一个子线程,那么当你希望手动宕掉socketserver时,肯定不希望它等每个子线程都断完成后,才宕机,你肯定希望它一下子就宕机,不管子线程。那么此时你就可以把这些子线程设置为守护线程。

Python3学习之路~9.2 操作系统发展史介绍、进程与线程区别、线程语法、join、守护线程的更多相关文章

  1. Python3学习之路~0 目录

    目录 Python3学习之路~2.1 列表.元组操作 Python3学习之路~2.2 简单的购物车程序 Python3学习之路~2.3 字符串操作 Python3学习之路~2.4 字典操作 Pytho ...

  2. Qt 学习之路 2(69):进程

    Qt 学习之路 2(69):进程 豆子 2013年11月9日 Qt 学习之路 2 15条评论 进程是操作系统的基础之一.一个进程可以认为是一个正在执行的程序.我们可以把进程当做计算机运行时的一个基础单 ...

  3. Qt 学习之路 2(16):深入 Qt5 信号槽新语法

    Qt 学习之路 2(16):深入 Qt5 信号槽新语法  豆子  2012年9月19日  Qt 学习之路 2  53条评论 在前面的章节(信号槽和自定义信号槽)中,我们详细介绍了有关 Qt 5 的信号 ...

  4. Python3学习之路~9.3 GIL、线程锁之Lock\Rlock\信号量、Event

    一 Python GIL(Global Interpreter Lock) 全局解释器锁 如果一个主机是单核,此时同时启动10个线程,由于CPU执行了上下文的切换,让我们宏观上看上去它们是并行的,但实 ...

  5. 微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇

    一.独立验证器 我上篇中我将AndCompositeValidator和OrCompositeValidator归为独立验证器,这2个验证器主要是为了第一类验证服务,可以进行多种验证组合在一起进行复杂 ...

  6. Python3学习之路~8.5 SocketServer实现多并发

    前面几节我们写的socket都只能实现服务端与一个客户端通信,并不能实现服务端与多客户端同时通信.接下来我们就来学习一下如何实现服务端同时与多个客户端通信,即并发. Socket Server soc ...

  7. Python3学习之路~5.5 sys模块

    用于提供对解释器相关的操作 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序 ...

  8. Python3学习之路~2.7 文件操作

    对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下 Somehow, it seems the love I knew was always the ...

  9. Python3学习之路~9.4 队列、生产者消费者模型

    一 队列queue 当必须在多个线程之间安全地交换信息时,队列在线程编程中特别有用. 队列的作用:1.解耦,使程序直接实现松耦合 2.提高处理效率 列表与队列都是有顺序的,但是他们之间有一个很大的区别 ...

随机推荐

  1. 商品规格笛卡尔积PHP

    <?php $color = array('red', 'green'); $size = array(39, 40, 41); $local = array('beijing', 'shang ...

  2. Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  3. 一起学爬虫——通过爬取豆瓣电影top250学习requests库的使用

    学习一门技术最快的方式是做项目,在做项目的过程中对相关的技术查漏补缺. 本文通过爬取豆瓣top250电影学习python requests的使用. 1.准备工作 在pycharm中安装request库 ...

  4. 关于postman各功能的说明及用法以及批量执行

    这玩意功能还不错,可以学学,在测试接口或者配合写代码测接口时是有帮助作用的.今天也去打听了一下,一下我就做了一下记录. 首先,主界面: 分开记录,写的详细一些. 左侧菜单栏: 主菜单(请求部分); 输 ...

  5. 解决'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '

    懒癌晚期,直接贴图 然后就解决了!

  6. 【redis】-- springboot集成redis及使用

    springboot自动配置的redis并不是特别好用,所以需要我们使用原生的jedis, 1.添加依赖 2.在application文件中配置 # Redis服务器地址 redis.host= # ...

  7. [jzoj]2505.【NOIP2011模拟7.29】藤原妹红

    Link https://jzoj.net/senior/#main/show/2505 Description 在幻想乡,藤原妹红是拥有不老不死能力的人类.虽然不喜欢与人们交流,妹红仍然保护着误入迷 ...

  8. Laravel使用心得

    Laravel使用心得 1.session使用 laravel的session使用时,不要使用exit和die,否则session会为空. 2.ajax提交注意框架对post的CSRF保护 在头加上& ...

  9. C# int[,] 和 int[][]

    int[] 一维数组 int[,]  二维数组 int[] []  交错数组 又称“数组的数组” 一维数组声明与初始化 声明: int[] a = new int[]; 声明与初始化: int arr ...

  10. 阿里云 ACP 考试学习过程分享

    目录 考证意义 学习方法 ACP 报名 学习安排[重要] 考试当天 其他 经验贴 考证意义 证多不压身,证比项目经历更具有说服力,证是行业的标准认证.更多时候,是有证的人说,"证其实不重要& ...