在多线程中,数据是共享,如何在多线程安全的通信,是首先要可虑的问题的

#线程间的通信

import time
import threading
from threading import RLock detail_url_list = [] lock = RLock() def get_detail_html(url):
#爬取文章详情页
global detail_url_list
#第一次我的想法也是用for循环,
# 但是你要知道,爬取文章的列表页要快于爬取文章详情页
#所以开启多个线程来爬取多个文章详情页
lock.acquire()
url = detail_url_list.pop()
print('get detail html started')
time.sleep(2)
print('get detail html end')
lock.release()
'''
for url in detail_url_list:
print('get detail html started')
time.sleep(2)
print('get detail html end')
''' def get_detail_url(url):
#爬取文章列表页
global detail_url_list
print('get detail url started')
time.sleep(4)
for i in range(20):
detail_url_list.append('http://projectsedu.com/{id}'.format(id=i))
print('get detail url end') #需求就是爬取文章列表页的url给文章详情页的url爬取:
#这个时候,设计到文章间的资源通信 #第一种方法就是 共享变量(共享变量其实就是全局变量,给各个函数调用)
#具体方法如下: if __name__ == '__main__':
# thread1 = threading.Thread(target=get_detail_html,args=(('',)))
for i in range(10):
thread1 = threading.Thread(target=get_detail_html)
thread1.start()
thread2 = threading.Thread(target=get_detail_url,args=(('http://bolezaixian.com',)))
thread2.start()
# start_time = time.time()
# thread1.setDaemon(True)#设置线程1为守护线程
# thread1.start()
# thread2.start()
# thread2.join()
# print('last time:{}'.format(time.time()-start_time))
共享变量也是要枷锁的。
import threading
from threading import Lock
#把共享变量存在settings配置文件中
import settings
import time lock = Lock() def get_detail_html():
#爬取文章详情页 detail_url_list=settings.detail_list_url
#第一次我的想法也是用for循环,
# 但是你要知道,爬取文章的列表页要快于爬取文章详情页
#所以开启多个线程来爬取多个文章详情页
while True:
try:
if len(detail_url_list):
# lock.acquire()
url = detail_url_list.pop()
print('get detail html started')
time.sleep(2)
print('get detail html end')
# lock.release()
except Exception as e:
print(e)
print('线程已运行完了')
break
'''
for url in detail_url_list:
print('get detail html started')
time.sleep(2)
print('get detail html end')
''' def get_detail_url():
#爬取文章列表页 detail_url_list = settings.detail_list_url
print('get detail url started')
time.sleep(4)
for i in range(20):
detail_url_list.append('http://projectsedu.com/{id}'.format(id=i))
print('get detail url end') if __name__ == '__main__':
start_time = time.time()
for i in range(10):
t = threading.Thread(target=get_detail_html)
t.start() t1 = threading.Thread(target=get_detail_url)
t1.start()
t1.join() print('total_time:{}'.format(time.time()-start_time))
#通过queue的方式进行线程间同步通信

-----------------------------------------------------------------------------------------------------------------

from queue import Queue

import time
import threading def get_detail_html(queue):
#爬取文章详情页
while True:
url = queue.get() #get()方法是一个阻塞的方法,如果queue是空队列,它一直会阻塞在这 print('get detail html started')
time.sleep(2)
print('get detail html end') def get_detail_url(queue):
#爬取文章列表页 while True:
print('get detail url started')
time.sleep(2)
for i in range(20):
queue.put("https://projectsedu.com/{id}".format(id=i))
print('get detail url end') if __name__ == "__main__":
detail_url_queue = Queue(maxsize=1000)#队列里面一定要设置下,maxsize的最大值,防止内存过大 thread_detail_url = threading.Thread(target=get_detail_url,args=((detail_url_queue,))) for i in range(10):
html_thread = threading.Thread(target=get_detail_html,args=((detail_url_queue,)))
html_thread.start() detail_url_queue.task_done()
#队列调用join()方法阻塞在这,只有调用task_done()方法队列才结束,主线程才能运行。
detail_url_queue.join() qsize()方法判断队列的大小,empty()方法判断队列是否为空,如果为空,get()是会阻塞在哪,full()方法判断队列是否已满,如果以满,put()方法是会阻塞在哪的

线程间通信共享变量和queue的更多相关文章

  1. python 线程间通信之Condition, Queue

    Event 和 Condition 是threading模块原生提供的模块,原理简单,功能单一,它能发送 True 和 False 的指令,所以只能适用于某些简单的场景中. 而Queue则是比较高级的 ...

  2. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  3. volatile关键字与线程间通信

    >>Java内存模型 现在计算机普遍使用多处理器进行运算,并且为了解决计算机存储设备和处理器的运算速度之间巨大的差距,引入了高速缓存作为缓冲,缓存虽然能极大的提高性能,但是随之带来的缓存一 ...

  4. 线程间通信的三种方式(NSThread,GCD,NSOperation)

    一.NSThread线程间通信 #import "ViewController.h" @interface ViewController ()<UIScrollViewDel ...

  5. 源码分析Android Handler是如何实现线程间通信的

    源码分析Android Handler是如何实现线程间通信的 Handler作为Android消息通信的基础,它的使用是每一个开发者都必须掌握的.开发者从一开始就被告知必须在主线程中进行UI操作.但H ...

  6. 如何使用 volatile, synchronized, final 进行线程间通信

    原文地址:https://segmentfault.com/a/1190000004487149.感谢作者的无私分享. 你是否真正理解并会用volatile, synchronized, final进 ...

  7. Android线程间通信机制——深入理解 Looper、Handler、Message

    在Android中,经常使用Handler来实现线程间通信,必然要理解Looper , Handler , Message和MessageQueue的使用和原理,下面说一下Looper , Handl ...

  8. Java多线程:线程间通信之volatile与sychronized

    由前文Java内存模型我们熟悉了Java的内存工作模式和线程间的交互规范,本篇从应用层面讲解Java线程间通信. Java为线程间通信提供了三个相关的关键字volatile, synchronized ...

  9. Android中线程间通信原理分析:Looper,MessageQueue,Handler

    自问自答的两个问题 在我们去讨论Handler,Looper,MessageQueue的关系之前,我们需要先问两个问题: 1.这一套东西搞出来是为了解决什么问题呢? 2.如果让我们来解决这个问题该怎么 ...

随机推荐

  1. 【LuoguP5383】[模板]普通多项式转下降幂多项式

    传送门 Sol (怎么老是有人喜欢出新的多项式毒瘤板子,懒得整到一起了) 核心就是把 幂用下降幂来代替. 使用斯特林数展开幂为下降幂: \[x^n=\sum_{i=0}^n{x\choose i}i! ...

  2. ython CGI编程Ⅱ

    HTTP头部 hello.py文件内容中的" Content-type:text/html"即为HTTP头部的https://www.xuanhe.net/一部分,它会发送给浏览器 ...

  3. 关于C#的学习

    长期以来对C#的认识一直停留在微软件开发的完全面向对象的语言的模糊印象上,对其工程也缺乏多文件以上级别的修改能力,而当前流行度的驱使下,想深入了解它并运用. 于是从git上下载了一个C#开源项目,打开 ...

  4. OpenCV笔记(3)(Canny边缘检测、高斯金字塔、拉普拉斯金字塔、图像轮廓、模板匹配)

    一.Canny边缘检测 Canny边缘检测是一系列方法综合的结果.其中主要包含以下步骤: 1.使用高斯滤波器,平滑图像,滤除噪声. 2.计算图像中每个像素点的梯度强度和方向. 3.应用非极大值抑制(N ...

  5. nginx命令和配置

    centos 6.8安装的nginx 1.12.2 1.nginx常用的命令 使用nginx命令前,进入到/usr/local/nginx/sbin/目录 1)查看nginx版本 进入到/usr/lo ...

  6. 2、DockPanel

    DockPanel——停靠面板,内部控件或容器可以放置在上.下.左(默认).右.类似于Java AWT布局中的BorderLayout. 但与BorderLayout不同的是,每一个区域可以同时放置多 ...

  7. jquery text选择器 语法

    jquery text选择器 语法 作用::text 选择器选取类型为 text 的 <input> 元素.大理石平台检定规程 语法:$(":text") jquery ...

  8. Markdown 标记语言指北

    这是班刊约稿的一篇文章. 全文约6000字, 预计需要 60 分钟读完. Markdown 标记语言指北 TOC 什么是 Markdown? Markdown 可以用来干什么? 第一步? 一些专业一点 ...

  9. Map循环/迭代/遍历效率、性能问题。

    项目开发完毕,为了找点事打发一下时间,于是用findBugs插件对当前完工的项目进行扫描,发现了很多问题.其中有个关于性能的问题,在这里记录一下. 提示信息为:Inefficient use of k ...

  10. 隐藏表单域、URL重写、cookie、session

    隐藏表单域: 隐藏域是用来收集或发送信息的不可见元素,对于网页的访问者来说,隐藏域是看不见的.当表单被提交时,隐藏域就会将信息用你设置时定义的名称和值发送到服务器上. 代码格式:<input t ...