Condition是一个多线程协调通信的工具类,可以让某些线程一起等待某个条件(condition),只有满足条件时,线程才会被唤醒

condition中两个最重要的方法,一个是await,一个是signal方法

await:把当前线程阻塞挂起

signal:唤醒阻塞的线程

示例:

public class ConditionWait implements Runnable{

    private Lock lock;
private Condition condition; public ConditionWait(Lock lock, Condition condition) {
this.lock = lock;
this.condition = condition;
}
@Override
public void run() {
try {
lock.lock(); //竞争锁
try {
System.out.println("begin - ConditionWait");
condition.await();//阻塞(1. 释放锁, 2.阻塞当前线程, FIFO(单向、双向))
System.out.println("end - ConditionWait");
// condition.signal(); } catch (InterruptedException e) {
e.printStackTrace();
}
}finally {
lock.unlock();//释放锁
} } }
public class ConditionNotify implements Runnable{

    private Lock lock;
private Condition condition; public ConditionNotify(Lock lock, Condition condition) {
this.lock = lock;
this.condition = condition;
} @Override
public void run() {
try{
lock.lock();//获得了锁.
System.out.println("begin - conditionNotify");
condition.signal();//唤醒阻塞状态的线程 //if(uncondition){
// condition.await();
// }
//condition.notify; condition.await();
System.out.println("end - conditionNotify");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
public class App
{
public static void main( String[] args )
{
Lock lock=new ReentrantLock(); //重入锁
Condition condition=lock.newCondition(); //step 2
new Thread(new ConditionWait(lock,condition)).start();// 阻塞await
//step 1
//(condtion为空)
new Thread(new ConditionNotify(lock,condition)).start();//
}
}

线程awaitThread先通过lock.lock()方法获取锁成功后调用了condition.await方法进入等待队列,而另一个线程signalThread通过lock.lock()方法获取锁成功后调用了condition.signal或者signalAll方法,使得线程awaitThread能够有机会移入到同步队列中,当其他线程释放lock后使得线程awaitThread能够有机会获取lock,从而使得线程awaitThread能够从await方法中退出执行后续操作。如果awaitThread获取lock失败会直接进入到同步队列。

阻塞:await()方法中,在线程释放锁资源之后,如果节点不在AQS等待队列,则阻塞当前线程,如果在等待队列,则自旋等待尝试获取锁

释放:signal()后,节点会从condition队列移动到AQS等待队列,则进入正常锁的获取流程

Condition源码分析

调用Condition,需要获得Lock锁,所以意味着会存在一个AQS同步队列,

condition.await

调用Condition的await()方法(或者以await开头的方法),会使当前线程进入等待队列并释放锁,同时线程状态变为等待状态。当从await()方法返回时,当前线程一定获取了Condition相关联的锁

addConditionWaiter

这个方法的主要作用是把当前线程封装成Node,添加到等待队列。这里的队列不再是双向链表,而是单向链表

fullyRelease

fullRelease,就是彻底的释放锁,什么叫彻底呢,就是如果当前锁存在多次重入,那么在这个方法中只需要释放一次就会把所有的重入次数归零。

isOnSyncQueue

判断当前节点是否在同步队列中,返回false表示不在,返回true表示在

如果不在AQS同步队列,说明当前节点没有唤醒去争抢同步锁,所以需要把当前线程阻塞起来,直到其他的线程调用signal唤醒

如果在AQS同步队列,意味着它需要去竞争同步锁去获得执行程序执行权限

为什么要做这个判断呢?原因是在condition队列中的节点会重新加入到AQS队列去竞争锁。也就是当调用signal的时候,会把当前节点从condition队列转移到AQS队列

➢ 大家思考一下,基于现在的逻辑结构。如何去判断ThreadA这个节点是否存在于AQS队列中呢?

1. 如果ThreadA的waitStatus的状态为CONDITION,说明它存在于condition队列中,不在AQS队列。因为AQS队列的状态一定不可能有CONDITION

2. 如果node.prev为空,说明也不存在于AQS队列,原因是prev=null在AQS队列中只有一种可能性,就是它是head节点,head节点意味着它是获得锁的节点。

3. 如果node.next不等于空,说明一定存在于AQS队列中,因为只有AQS队列才会存在next和prev的关系

4. findNodeFromTail,表示从tail节点往前扫描AQS队列,一旦发现AQS队列的节点和当前节点相等,说明节点一定存在于AQS队列中

python学习之----爬取图片的更多相关文章

  1. [python学习] 简单爬取图片站点图库中图片

    近期老师让学习Python与维基百科相关的知识,无聊之中用Python简单做了个爬取"游讯网图库"中的图片,由于每次点击下一张感觉很浪费时间又繁琐.主要分享的是怎样爬取HTML的知 ...

  2. python +requests 爬虫-爬取图片并进行下载到本地

    因为写12306抢票脚本需要用到爬虫技术下载验证码并进行定位点击所以这章主要讲解,爬虫,从网页上爬取图片并进行下载到本地   爬虫实现方式: 1.首先选取你需要的抓取的URL:2.将这些URL放入待抓 ...

  3. Python爬虫学习 - day1 - 爬取图片

    利用Python完成简单的图片爬取 最近学习到了爬虫,瞬时觉得很高大上,想取什么就取什么,感觉要上天.这里分享一个简单的爬取汽车之家文章列表的图片教程,供大家学习. 需要的知识点储备 本次爬虫脚本依赖 ...

  4. python学习之——爬取网页信息

    爬取网页信息 说明:正则表达式有待学习,之后完善此功能 #encoding=utf-8 import urllib import re import os #获取网络数据到指定文件 def getHt ...

  5. python爬虫(爬取图片)

    python爬虫爬图片 爬虫爬校花网校花的图片 第一步 载入爬虫模块 #载入爬虫模块 import re #载入爬虫模块 import requests #载入爬虫模块 第二步 获得校花网的地址,获得 ...

  6. [Python学习] 简单爬取CSDN下载资源信息

    这是一篇Python爬取CSDN下载资源信息的样例,主要是通过urllib2获取CSDN某个人全部资源的资源URL.资源名称.下载次数.分数等信息.写这篇文章的原因是我想获取自己的资源全部的评论信息. ...

  7. Python爬虫--简单爬取图片

    今天晚上弄了一个简单的爬虫,可以爬取网页的图片,现在现在做一下准备工作. 需要的库:urllib 和 re urllib库可以理解为是一个url下载器,其中有三个重要的方法 urllib.urlope ...

  8. python网络爬虫&&爬取图片

    爬取学院官网数据from urllib.request import * #导入所有request urllib文件夹,request只是里面的一个模块from lxml import etree # ...

  9. Python 学习笔记---爬取海贼王动漫

    最近无聊整理的爬虫代码,可以自动爬取腾讯动漫的任意漫画,思路如下: 1. 先获取想下载的动漫url, 这里用了 getUrls ,直接获取动漫的最后一章 2. 然后进入到该动漫去获取要下载的图片url ...

随机推荐

  1. jp@gc - Stepping Thread Group配置解释描述

    测试环境 apache-jmeter-2.13   插件: https://jmeter-plugins.org/downloads/old/ http://pan.baidu.com/s/1gfC1 ...

  2. 基于MVC4+EasyUI的Web开发框架形成之旅(5)--框架总体界面介绍

    在前面介绍了一些关于最新基于MVC4+EasyUI的Web开发框架文章,虽然Web开发框架的相关技术文章会随着技术的探讨一直写下去,不过这个系列的文章,到这里做一个总结,展示一下整体基于MVC4+Ea ...

  3. ASP.NET AJAX入门系列(7):使用客户端脚本对UpdateProgress编程

    在本篇文章中,我们将通过编写JavaScript来使用客户端行为扩展UpdateProgress控件,客户端代码将使用ASP.NET AJAX Library中的PageRequestManager, ...

  4. Linux 建立 TCP 连接的超时时间分析(解惑)

    Linux 系统默认的建立 TCP 连接的超时时间为 127 秒,对于许多客户端来说,这个时间都太长了, 特别是当这个客户端实际上是一个服务的时候,更希望能够尽早失败,以便能够选择其它的可用服务重新尝 ...

  5. Qt 中的事件处理(二)

    1. 回顾事件传递的过程 ①源头:操作系统   操作系统检测到用户的动作时,就会产生一个系统消息,系统消息就会被发送到正在运行的Qt应用程序中, ②应用程序收到系统消息后, 他会将系统消息翻译成对应的 ...

  6. C++用 _findfirst 和 _findnext 查找文件

    一.这两个函数均在io.h里面.   二.首先了解一下一个文件结构体: struct _finddata_t {     unsigned    attrib;     time_t      tim ...

  7. 基于tensorflow的MNIST手写识别

    这个例子,是学习tensorflow的人员通常会用到的,也是基本的学习曲线中的一环.我也是! 这个例子很简单,这里,就是简单的说下,不同的tensorflow版本,相关的接口函数,可能会有不一样哟.在 ...

  8. SDRAM---页读写

    SDRAM---页读写 1.SDRAM页访问 一页通俗的来讲就是一行. SDRAM页写操作时序图: 2.DDR(经常被提起,但是我和你不熟) DDR的连续访问操作 给DDR一个write命令,同时给出 ...

  9. Delphi中使用ADO连接Excel

    第一部分: . 设置ADOConnection的ConnectionString属性的OLE DB的提供者要选择Microsoft Jet 4.0 OLE DB Provider(这本来是用于连接Ac ...

  10. 开IE时 暴卡

    待打开IE后,在“工具”-“管理加载项”中禁用所有加载项.