1.进程和线程

(1)进程是一个执行中的程序。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。进程也可以派生新的进程来执行其他任务,不过每个新进程都拥有自己的内存和数据栈,所以只能采用进程间通信(IPC)的方式共享信息。

(2)线程与进程类似,不过他们是在同一个进程下执行的,并共享相同的上下文。线程一般是以并发方式执行的,但是在单核CPU中真正的并发是不可能的,:每个线程运行一小会儿,然后让步给其他线(再次排队等待更多的CPU时间)。但是,多线程访问同一片数据,由于访问的顺序不同可能导致结构不一致。例如append(0-1)和print会同时有01

PS:内存中可以有许多程序,但是在任意给定时刻只能有一个程序在运行。同理,尽管Python 解释器中可以运行多个线程,但是在任意给定时刻只有一个线程会被解释器执行。

2.线程

线程相关的模块有thread和threading,其中threading是thread的改进和升级版,且thread模块有一个致命的缺点,在主线程退出之后,所有其他线程都会在没有清理的情况下直接退出。threading模块中加入守护线程概念,如果被指明为守护线程后主线程退出后不会等待守护线程执行完毕才吐出。整个Python 程序(可以解读为:主线程)将在所有非守护线程退出之后才退出,换句话说,就是没有剩下存活的非守护线程时。

主线程和子线程分别是什么?举例?

而主线程应该做一个好的管理者,负责了解每个单独的线程需要执行什么,每个派生的线程需要哪些数据或参数,这些线程执行完成后会提供什么结果。这样,主线程就可以收集每个线程的结果,然后汇总成一个有意义的最终结果。

(1)单线程:

我需要做两件事,只能做完一件再做第二件,排好队

# -*-coding:utf-8-*-
from time import ctime, sleep
import threading
loops = [4, 2] def loop(nloop,nsec):
print('start loop', nloop, 'at :', ctime())
sleep(nsec)
print('done loop', nloop, 'at:', ctime()) def main():
print('start at',ctime())
nloops = range(len(loops))
for i in nloops:
loop(i, loops[i]) print('DONE AT:', ctime())
if __name__ == '__main__':
main()

  

 返回结果:

start at Sun Dec 3 12:10:52 2017
start loop 0 at : Sun Dec 3 12:10:52 2017
done loop 0 at: Sun Dec 3 12:10:56 2017
start loop 1 at : Sun Dec 3 12:10:56 2017
done loop 1 at: Sun Dec 3 12:10:58 2017
DONE AT: Sun Dec 3 12:10:58 2017

(2) 多线程:(建立threads实例,传给他一个函数)

# -*-coding:utf-8-*-
from time import ctime, sleep
import threading
loops = [4, 2] def loop(nloop,nsec):
print('start loop', nloop, 'at :', ctime())
sleep(nsec)
print('done loop', nloop, 'at:', ctime()) def main():
print('start at',ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = threading.Thread(target=loop,args=(i,loops[i]))
threads.append(t)
for i in nloops: # start threads 此处并不会执行线程,而是将任务分发到每个线程,同步线程。等同步完成后再开始执行start方法
threads[i].start()
for i in nloops: # jion()方法等待线程完成
threads[i].jion()
print('DONE AT:', ctime())
if __name__ == '__main__':
main()

  

运行结果:

start at Sun Dec 3 12:08:23 2017
start loop 0 at : Sun Dec 3 12:08:23 2017
start loop 1 at : Sun Dec 3 12:08:23 2017
done loop 1 at: Sun Dec 3 12:08:25 2017
done loop 0 at: Sun Dec 3 12:08:27 2017
DONE AT: Sun Dec 3 12:08:27 2017

可以看到loop0和loop1同时进行,当时间较长的子线程loop0完成后,主线程print('DONE AT:', ctime())开始任务

(3)多线程(创建threads实例,传递给他一个可调用的类实例):

# -*-coding:utf-8-*-
from time import ctime, sleep
import threading
loops = [4, 2] class MyThread(object):
def __init__(self, func, args, name=''):
self.name = name
self.func = func
self.args = args def __call__(self):
self.func(*self.args) def loop(nloop, nsec):
print('start loop', nloop, 'at :', ctime())
sleep(nsec)
print('done loop', nloop, 'at:', ctime()) def main():
print('start at',ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = threading.Thread(target=MyThread(loop, (i, loops[i]), loop.__name__))
threads.append(t)
for i in nloops: # start threads 此处并不会执行线程,而是将任务分发到每个线程,同步线程。等同步完成后再开始执行start方法
threads[i].start()
for i in nloops: # jion()方法等待线程完成
threads[i].join()
print('DONE AT:', ctime())
if __name__ == '__main__':
main()

  

join函数的原理就是一次检验线程池中的线程是否结束,没有结束就阻塞直到线程结束。如果结束则就跳转执行下一个线程的join函数。如果不用join(),主线程跑的比子线程快会拿不到结果

(3)通过多线程获取返回值

# -*-coding:utf-8-*-
from time import ctime, sleep
import threading
import numpy as np
import collections loops = ['广州', '北京']
t_list = ['01', '02', '03']
cldas_sum = collections.deque() class MyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
self.result = self.func(*self.args) def get_result(self):
try:
return self.result
except Exception:
return None def loop(nloop):
for j in t_list:
cldas_values = []
for k in range(4):
cldas_value = nloop + str(k)
cldas_values.append(cldas_value)
cldas_values.append(j)
cldas_values.append(nloop)
cldas_sum.append(cldas_values)
print(id(cldas_values))
#print(cldas_sum)
return cldas_sum def main():
print('start at', ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = MyThread(loop, (loops[i],), loop.__name__)
threads.append(t)
for i in nloops: # start threads 此处并不会执行线程,而是将任务分发到每个线程,同步线程。等同步完成后再开始执行start方法
threads[i].start()
for i in nloops: # jion()方法等待线程完成
threads[i].join()
print(threads[1].get_result())
print('DONE AT:', ctime()) if __name__ == '__main__':
main()

  

 写这个脚本的一个目的就是看所有脚本共同调用同一个函数,每个脚本都在这个函数中都有一个相同的变量,那么这个变量会被共用还是每个线程自己各有一个闭包。不过函数内定义的变量是闭包,调用函数时创建,返回时销毁。

最终返回结果如下:

start at Tue Dec 5 10:32:38 2017
728072411976
728072411848
728072411784
728072411656
728072364680
728072364808
deque([['广州0', '广州1', '广州2', '广州3', '01', '广州'], ['广州0', '广州1', '广州2', '广州3', '02', '广州'], ['广州0', '广州1', '广州2', '广州3', '03', '广州'], ['北京0', '北京1', '北京2', '北京3', '01', '北京'], ['北京0', '北京1', '北京2', '北京3', '02', '北京'], ['北京0', '北京1', '北京2', '北京3', '03', '北京']])
DONE AT: Tue Dec 5 10:32:38 2017

需要注意的是:

(1)如果多个线程共用一个公共数据,那么我们需要做的就是将这个公共数据设置成队列格式,要不然多个线程共同访问这个数据可能会出错,需要加锁。设置成队列比加锁再放锁效率高多了

(2)线程之间同一个变量id都不一样,还是不知道是否其他线程会涉足另一个线程

 

Python建立多线程任务并获取每个线程返回值的更多相关文章

  1. 获取Java线程返回值的几种方式

    在实际开发过程中,我们有时候会遇到主线程调用子线程,要等待子线程返回的结果来进行下一步动作的业务. 那么怎么获取子线程返回的值呢,我这里总结了三种方式: 主线程等待. Join方法等待. 实现Call ...

  2. ARTS-S 获取子线程返回值注意事项

    #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h& ...

  3. 十、获取异步线程返回值Callable

    一.简介 异步线程的实现接口Runnable是无法获得返回结果的,而另一个接口Callable可以返回结果.并通过如Future等方式来获取异步结果. 二.代码示例 import java.util. ...

  4. ARTS-S C语言主线程获取子线程返回值

    #include<stdio.h> #include<stdlib.h> #include <pthread.h> typedef struct { int stu ...

  5. python获取线程返回值

    python获取线程返回值 前言 工作中的需求 将前端传过来的字符串信息通过算法转换成语音,并将语音文件返回回去 由于算法不是我写的,只需要调用即可,但是算法执行速度相当缓慢 我的优化思路是,将前端的 ...

  6. Java多线程和并发(四),线程返回值获取方式和Callable接口

    目录 1.主线程等待法 2.使用Thread类的join()阻塞当前线程,等待子线程执行完毕 3.通过Callable接口实现:通过FutureTask Or线程池获取 四.线程返回值获取方式和Cal ...

  7. python asyncio 获取协程返回值和使用callback

    1. 获取协程返回值,实质就是future中的task import asyncioimport timeasync def get_html(url): print("start get ...

  8. Android平台调用Web Service:线程返回值

    接上文 前文中的遗留问题 对于Java多线程的理解,我曾经只局限于实现Runnable接口或者继承Thread类.然后重写run()方法.最后start()调用就算完事,可是一旦涉及死锁以及对共享资源 ...

  9. 无废话Android之activity的生命周期、activity的启动模式、activity横竖屏切换的生命周期、开启新的activity获取他的返回值、利用广播实现ip拨号、短信接收广播、短信监听器(6)

    1.activity的生命周期 这七个方法定义了Activity的完整生命周期.实现这些方法可以帮助我们监视其中的三个嵌套生命周期循环: (1)Activity的完整生命周期 自第一次调用onCrea ...

随机推荐

  1. keras实例学习-双向LSTM进行imdb情感分类

    源码:https://github.com/keras-team/keras/blob/master/examples/imdb_bidirectional_lstm.py 及keras中文文档 1. ...

  2. TVTK安装

    首先感觉到的一点就是在https://www.lfd.uci.edu/~gohlke/pythonlibs/#chaco这个比较受欢迎的下载Python库的网站上下载大于20mb的whl文件时就很可能 ...

  3. 解决异地服务器接口访问跨域,node构建反向代理

    跨域对于前端来说是一个老大难的问题,许多方法如jsonp.document.domain + iframe...都有或多或少的问题,一个最佳实践就是通过服务器nginx做反向代理,但奈何不懂相关知识, ...

  4. Pycharm进行版本管理

    即然pycharm为python提供了这么强大的IDE,那么,我们代码管理,没理由不用版本管理工具Git,SVN等等 在pychram中使用GitHub进行代码管理;需要准备: 1)GitHub帐号: ...

  5. 34.js----JS 开发者必须知道的十个 ES6 新特性

    JS 开发者必须知道的十个 ES6 新特性 这是为忙碌的开发者准备的ES6中最棒的十个特性(无特定顺序): 默认参数 模版表达式 多行字符串 拆包表达式 改进的对象表达式 箭头函数 =&> ...

  6. ecshop 订单状态

    ecshop的订单状态都是在ecs_order_info表中的字段里. 订单状态 未确认 取消 确认 已付款 配货中 已发货 已收货 退货 order_status 0 2 1 1 1 5 5 4 s ...

  7. HttpServletRequest常用方法

    1.获取客户机信息 getRequestURL:该方法返回客户端发出请求时的完整URL getRequestURI:该方法返回请求行中的资源名部分 getQueryString:该方法返回请求中的参数 ...

  8. 软工网络15团队作业4——Alpha阶段敏捷冲刺5.0

    1.每天举行站立式会议,提供当天站立式会议照片一张. 2.项目每个成员的昨天进展.存在问题.今天安排. 成员 昨天已完成 今天计划完成 郭炜埕 完善新建话题界面 实现前端各界面的跳转连接 郑晓丽 进行 ...

  9. date的用法

    date -d "-1 month" "+%T"  当前时间减少一个月 +%T 简便表示时分秒 +%F 简便表示年月日 date +%Y 四位年份 date + ...

  10. 20155228 2016-2017-2 《Java程序设计》第4周学习总结

    20155228 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 继承与多态 继承:在Java中,子类只能继承一个父类,关键字为extends,子类和父类之间 ...