join(long)方法的源代码

     public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0; if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
} if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

sleep(long)方法的源代码

public static native void sleep(long millis) throws InterruptedException;

从源代码中可以发现,join(long)方法内部使用wait(long)实现,所以join(long)方法执行后会释放锁,所以其他线程就可以调用此线程中的同步方法

验证sleep(long)方法会不会释放锁

--------------------------------------------------------线程类--------------------------------------------------------

 package com.qf.test04.thread;

 /**
* @author qf
* @create 2018-09-20 15:22
*/
public class ThreadA extends Thread {
private ThreadB threadB; public ThreadA(ThreadB threadB) {
this.threadB = threadB;
} @Override
public void run() {
try {
synchronized (threadB){
threadB.start();
Thread.sleep(6000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
 package com.qf.test04.thread;

 /**
* @author qf
* @create 2018-09-20 15:22
*/
public class ThreadB extends Thread {
@Override
public void run() {
try {
System.out.println("b run begin time = "+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("b run --end time = "+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
} public synchronized void bService(){
System.out.println("bService time = "+System.currentTimeMillis());
}
}
 package com.qf.test04.thread;

 /**
* @author qf
* @create 2018-09-20 15:22
*/
public class ThreadC extends Thread {
private ThreadB threadB; public ThreadC(ThreadB threadB) {
this.threadB = threadB;
} @Override
public void run() {
threadB.bService();
}
}

--------------------------------------------------------测试类--------------------------------------------------------

 package com.qf.test04;

 import com.qf.test04.thread.ThreadA;
import com.qf.test04.thread.ThreadB;
import com.qf.test04.thread.ThreadC; /**
* @author qf
* @create 2018-09-20 15:22
*/
public class Run {
public static void main(String[] args) {
try {
ThreadB b = new ThreadB();
ThreadA a = new ThreadA(b);
a.start();
Thread.sleep(1000);
ThreadC c = new ThreadC(b);
c.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

-------------------------------------------------------打印输出------------------------------------------------------

b run begin time = 1537429005098
b run --end time = 1537429010098
bService time = 1537429011098

结果显示只有a线程执行完毕(sleep了6000ms),c线程才能执行,所以sleep方法并没有释放锁

验证join(long)方法释放锁

修改ThreadA.java中的代码

-----------------------------------------------------ThreadA.java----------------------------------------------------

 package com.qf.test04.thread;

 /**
* @author qf
* @create 2018-09-20 15:22
*/
public class ThreadA extends Thread {
private ThreadB threadB; public ThreadA(ThreadB threadB) {
this.threadB = threadB;
} @Override
public void run() {
try {
synchronized (threadB){
threadB.start();
//Thread.sleep(6000);
threadB.join();
for (int i = 0; i < Integer.MAX_VALUE ; i++) {
//用于耗时
String newString = new String();
Math.random();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

-------------------------------------------------------打印输出------------------------------------------------------

b run begin time = 1537429346791
bService time = 1537429347790
b run --end time = 1537429351793

bService在1000后执行打印,说明c线程获得了threadB的锁,所以a线程在join后释放了锁

join(long)方法和sleep(long)方法的比较的更多相关文章

  1. $(document).ready()即$()方法和window.onload方法的比较

    以浏览器装载文档为例,我们都知道在页面完毕后,浏览器会通过JavaScript为DOM元素添加事件.在常规的JavaScript代码中,通常使用window.onload方法,而在jQuery中,使用 ...

  2. Server.Transfer方法,Server.Execute方法和Response.Redirect方法有什么异同

    (1)Server.Transfer方法: Server.Transfer("m2.aspx");//页面转向(服务器上执行). 服务器停止解析本页,保存此页转向前的数据后,再使页 ...

  3. java——多线程——单例模式的static方法和非static方法是否是线程安全的?

    单例模式的static方法和非static方法是否是线程安全的? 答案是:单例模式的static方法和非static方法是否是线程安全的,与单例模式无关.也就说,如果static方法或者非static ...

  4. synchronized 修饰在 static方法和非static方法的区别

    Java中synchronized用在静态方法和非静态方法上面的区别 在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以synchroniz ...

  5. $(document).ready()方法和window.onload()方法

    $(document).ready()方法和window.onload()方法 $(document).ready()方法是JQuery中的方法,他在DOM完全就需时就可以被调用,不必等待这些元素关联 ...

  6. Html.Partial方法和Html.RenderPartial方法

    分布视图 PartialView 一般是功能相对独立的,类似用户控件的视图代码片段,可以被多个视图引用,引用方式如下. 1,Html.Partial方法和Html.RenderPartial方法 静态 ...

  7. tornado的IOLoop.instance()方法和IOLoop.current()方法区别

    在使用tornado时,经常有人疑惑IOLoop.instance()方法和IOLoop.current()方法的区别是什么. IOLoop.instance() 返回一个全局 IOLoop实例. 大 ...

  8. 【转载】C#中double.TryParse方法和double.Parse方法的异同之处

    在C#编程过程中,double.TryParse方法和double.Parse方法都可以将字符串string转换为double类型,但两者还是有区别,最重要的区别在于double.TryParse方法 ...

  9. 【转载】 C#中decimal.TryParse方法和decimal.Parse方法的异同之处

    在C#编程过程中,decimal.TryParse方法和decimal.Parse方法都可以将字符串string转换为decimal类型,但两者还是有区别,最重要的区别在于decimal.TryPar ...

随机推荐

  1. kmp next数组的模板

    string s; int Next[MAX]; int len; void get_next() { ,j=-; Next[i]=j;//初始化,next[0]=-1:-1表示没有前缀等于后缀. ; ...

  2. 全局唯一iD的生成 雪花算法详解及其他用法

    一.介绍 雪花算法的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等. 自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景.GUID:采用无意义字符串,数据量增大时造成 ...

  3. ionic3配合使用docker build代码时的显示仓库配置问题

    1.未配置前的报错提示: 会一直提示push失败 2.在/etc/docker目录下新建 daemon.json文件,内容为: { "insecure-registries":[& ...

  4. NFS 共享存储实战

    目录 NFS 共享存储实战 一.NFS概述 二.NFS部署 部署NFS客户端backup和web01 统一web.nfs.backup的用户权限 代码部署步骤 三.NFS配置详解 NFS存储小结 四. ...

  5. java环境--JDK和Tomcat在linux上的安装和配置

    Tomcat在Linux上的安装与配置 以下使用的Linux版本为: Redhat Enterprise Linux 7.0 x86_64,Tomcat版本为tomcat-7.0.54.1.下载JDK ...

  6. 【Database】MySQL实战45讲

    01 | 基础架构:一条SQL查询语句是如何执行的? 1. MySQL 的基本架构图: MySQL可以分成: Server层 和 存储引擎层 两部分. Server层:包含连接器.查询缓存.分析器.优 ...

  7. Java网络编程:什么是Socket编程?

    所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 我们开发的网络应用 ...

  8. cpanle/Apache 强制http跳转到https

    因为租的虚拟主机是使用Cpanel,按照网上找的文章,处理的步骤如下: 打开Cpanel面板-文件管理器-设置(在页面的右上角)-勾选显示隐藏文件(dotfiles)-save . 找到网站所在的目录 ...

  9. 常用Concurrent.util包工具类——高并发

    一 Concurrent.util常用类: 1. CyclicBarrier: 假设有场景:每个线程代表一个跑步运动员,当运动员都准备好后,才一起出发只要有一个人没有准备好,大家都等待. import ...

  10. String path = request.getContextPath();报错

    String path = request.getContextPath();报错 1. 右击该项目 - Build Path - Configure Build Path , 在 Libraries ...