一 操作系统发展史介绍

参考链接: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. 【由浅入深理解java集合】(四)——集合 Queue

    今天我们来介绍下集合Queue中的几个重要的实现类.关于集合Queue中的内容就比较少了.主要是针对队列这种数据结构的使用来介绍Queue中的实现类. Queue用于模拟队列这种数据结构,队列通常是指 ...

  2. select获取选中的option(包含value和text,重点是text怎么获取)

    简单描述:后台需要获取到select标签选择的内容,也就是text,该怎么取呢?很简单. 代码: //hml代码<div class="col-md-6"> <l ...

  3. ASP.NET 多环境下配置文件web.config的灵活配置

    调试,发布Asp.net程序的时候,开发环境和发布环境的Web.Config往往不同,比如connectionstring等.如果常常有调试,发布的需求,就需要常常修改web.config文件,这往往 ...

  4. #Node.js的fs导入遇到的问题和解决方案

    一直在使用VS Code,今天打算用Node.js进行文件IO时候遇到了一些问题,fs是Node.js的核心功能之一,一开始我用Javascript编写fs模块的导入. var fs = requir ...

  5. ionic 3 常见报错及解决办法

    用ionic 3开发也有一段时间了,现在总结下开发中遇到的报错,以及解决办法: ERROR DOMException: Failed to execute 'setAttribute' on 'Ele ...

  6. %E6%9D%8E%E9%9B%B7是什么编码

    在这个网站上可以进行解码http://tool.chinaz.com/Tools/URLEncode.aspx

  7. Linux安装Tomcat-Nginx-FastDFS-Redis-Solr-集群——【第九集-补充-之安装iptables】

    1,安装完了jdk,tomcat,启动tomcat的bin/startup.sh后,发现在浏览器输入公网ip地址和tomcat的默认(server.xml)中的端口port:8080,无法访问,这主要 ...

  8. springboot的jar包

    公用jar包放在api层.有些却包的不用增加pom文件.将已存在的jar包加入即可

  9. ASP.NET Core 3.0预览版体验

    目前.NET Core 3.0的版本为.NET Core 3.0 Preview 3,对应ASP.NET Core 3.0 Preview 3. ASP.NET Core 3.0 之后将不再支持.NE ...

  10. PostgreSQL自学笔记:9 索引

    9 索引 9.1 索引简介 索引是对数据库表中一列或多列值进行排序的一种结构,使用 索引可提高数据库中特定数据的查询速度 9.1.1 索引的含义和特点 索引是一种单独的.存储在磁盘上的数据库结构,他们 ...