一 操作系统发展史介绍

参考链接: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. SSH阅读笔记

    1.SSH单阶人脸段检测器,在不同层检测不同scale的人脸,而不是使用mtcnn中金字塔的方式,从而实现加速. 2.SSH的整体结构,3个module的stride分别为8,16,32,使用不同的感 ...

  2. python3 基础语法(一)

    一.标识符: 第一个字符必须是字母表中字母或下划线 “_” . 例如: #!/usr/bin/env python #coding=utf-8 a = 3 _aa = 3 a3 = 3 _aa3 = ...

  3. (转发)Navicat 远程连接 Linux服务器上的MySQL数据库

    授权法: 在安装mysql的机器上运行: 1.# ./bin/mysql -uroot -p //这样应该可以进入MySQL服务器 2.mysql> GRANT ALL PRIVILEGES O ...

  4. Spring Boot项目部署到外部Tomcat服务器

    2017年04月27日 23:33:52 阅读数:7542 前言 Spring Boot项目一般都是内嵌tomcat或者jetty服务器运行,很少用war包部署到外部的服务容器,即使放到linux中, ...

  5. leetcode目录

    Leetcode 1. 数组 2. 动态规划 3. 字符串 4. 链表.双指针.排序 5. 树 6. 回溯算法.贪心算法.分治算法.

  6. C# 解压与压缩文件

    解压文件 ,引用 SharpZipLib.dll类库 方法一: public void UnGzipFile(string zipfilename) { //同压缩文件同级同名的非压缩文件路径 var ...

  7. MariaDB报错Plugin 'InnoDB' init function returned error.解决方案

    重新安装MariaDB后,服务一直启动不起来,查看日志有以下错误: InnoDB: No valid checkpoint found. InnoDB: If you are attempting d ...

  8. Oracle做insert或者update时未提交事务导致表锁定解决办法

    //查看被锁定表有几个 select object_name,machine,s.sid,s.serial# from v$locked_object l,dba_objects o ,v$sessi ...

  9. 解决ubuntu下firefox无法在线播放音频和视频的问题

    原因 Ubuntu 为了规避专利和版权问题,很多东西没有预装,比如音视频解码器AAC. 那么为什么明明 Ubuntu 上没有AAC解码器, Chrome 却可以正常播放呢,自然的想法是 Chrome ...

  10. 调试webpack配置文件

    webpack运行在nodejs上,调试webpack就相当于调试nodejs程序.下面介绍一种通用的办法. 1.配置package.json,加一个debug. { 'scripts': { 'de ...