多线程学习-基础(四)常用函数说明:sleep-join-yield
一、常用函数的使用
(1)Thread.sleep(long millis):在指定的毫秒内让当前正在执行的线程休眠(暂停执行),休眠时不会释放当前所持有的对象的锁。
(2)join():主线程等待子线程终止后才可以终止
使用方式:
join()是Thread的一个方法,启动线程后可以直接调用,即join()的作用是:“等待该线程终止”,这里需要解释的是“该线程终止”是指主线程等待子线程的终止。
Thread t = new AThread();
t.start();
t.join();
为什么要用join()方法:
在很多情况下,主线程生成并启动了子线程,如果子线程要进行大量的耗时运算,主线程往往在子线程之前结束,但是如果主线程处理完其他事务后,需要用到子线程的处理结果,也就是说主线程需要等待子线程结束之后才可以结束,这个时候就需要用到join()方法了。
测试案例:
不加join()方法
package com.jason.comfuns.join;
/**
* 多线程学习
* @function 不使用Thread.join()方法:测试在主线程中启动子线程时:主子线程的执行顺序
* @author 小风微凉
* @time 2018-4-21 下午12:56:31
*/
public class Thread_join_Action extends Thread {
private String thname;
public Thread_join_Action(String name){
super(name);
this.thname=name;
}
public void run(){
System.out.println(Thread.currentThread().getName()+"线程运行开始!");
for(int i=0;i<5;i++){
System.out.println("子线程"+thname+"运行:"+i);
try {
sleep((int)Math.random()*10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"线程运行结束!");
}
/**
* 启动测试程序
* @param args
*/
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
Thread_join_Action thread1=new Thread_join_Action("A");
Thread_join_Action thread2=new Thread_join_Action("B");
thread1.start();
thread2.start();
System.out.println(Thread.currentThread().getName()+"主线程运行结束!");
}
}
运行结果:(主线程:main在子线程A和子线程B之前结束了)
main主线程运行开始!
main主线程运行结束!
A线程运行开始!
子线程A运行:0
B线程运行开始!
子线程B运行:0
子线程A运行:1
子线程B运行:1
子线程A运行:2
子线程B运行:2
子线程A运行:3
子线程B运行:3
子线程A运行:4
子线程B运行:4
A线程运行结束!
B线程运行结束!
加入join():(所有子线程都调用join())
测试案例:
package com.jason.comfuns.join;
/**
* 多线程学习
* @function 不使用Thread.join()方法:测试在主线程中启动子线程时:主子线程的执行顺序
* @author 小风微凉
* @time 2018-4-21 下午12:56:31
*/
public class Thread_join_Action extends Thread {
private String thname;
public Thread_join_Action(String name){
super(name);
this.thname=name;
}
public void run(){
System.out.println(Thread.currentThread().getName()+"线程运行开始!");
for(int i=0;i<5;i++){
System.out.println("子线程"+thname+"运行:"+i);
try {
sleep((int)Math.random()*10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"线程运行结束!");
}
/**
* 启动测试程序
* @param args
*/
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
Thread_join_Action thread1=new Thread_join_Action("A");
Thread_join_Action thread2=new Thread_join_Action("B");
thread1.start();
thread2.start();
//开始调用子线程thread1的join()
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//开始调用子线程thread2的join()
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"主线程运行结束!");
}
}
运行结果:
执行结果:(主线程main,在子线程A和子线程B执行结束之后,才结束,前提:子线程A和子线程B都必须调用join())
main主线程运行开始!
A线程运行开始!
B线程运行开始!
子线程B运行:0
子线程A运行:0
子线程B运行:1
子线程A运行:1
子线程B运行:2
子线程B运行:3
子线程A运行:2
子线程B运行:4
子线程A运行:3
B线程运行结束!
子线程A运行:4
A线程运行结束!
main主线程运行结束!
加入join():(部分子线程都调用join())
测试案例:
package com.jason.comfuns.join;
/**
* 多线程学习
* @function 不使用Thread.join()方法:测试在主线程中启动子线程时:主子线程的执行顺序
* @author 小风微凉
* @time 2018-4-21 下午12:56:31
*/
public class Thread_join_Action extends Thread {
private String thname;
public Thread_join_Action(String name){
super(name);
this.thname=name;
}
public void run(){
System.out.println(Thread.currentThread().getName()+"线程运行开始!");
for(int i=0;i<5;i++){
System.out.println("子线程"+thname+"运行:"+i);
try {
sleep((int)Math.random()*10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"线程运行结束!");
}
/**
* 启动测试程序
* @param args
*/
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"主程序运行开始!");
Thread_join_Action thread1=new Thread_join_Action("A");
Thread_join_Action thread2=new Thread_join_Action("B");
thread1.start();
thread2.start();
//开始调用子线程thread1的join()------只有子线程A调用join()
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"主程序运行结束!");
}
}
运行结果:(只有在主线程中的调用了join()方法的子线程运行结束,主线程才会结束,没有调用join()方法的子线程不在此列)
main主程序运行开始!
B线程运行开始!
A线程运行开始!
子线程A运行:0
子线程B运行:0
子线程A运行:1
子线程B运行:1
子线程A运行:2
子线程B运行:2
子线程A运行:3
子线程B运行:3
子线程A运行:4
子线程B运行:4
A线程运行结束!
main主程序运行结束!
B线程运行结束!
(3)yield():暂停当前正在执行的线程,并执行其他线程。
Thread.yield():暂停当前正在执行的线程,并执行其他线程。
yield()方法应该做的是让当前行线程回到可运行状态(就绪状态),以允许其他相同优先级或更高优先级的线程获得运行机会。因此,使用yield()方法的目的是让相同优先级的线程之间能够适当的轮转执行。但是,实际上无法保证yield()达到让步目的,因为让步线程(yield()的调用对象线程)还有可能被线程调度程序再次选中。
结论:
yield()从未导致:线程转到等待、休眠、阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态(就绪状态),但是有可能没效果。
简单案例: (测试2个同优先级别的线程:在调用yield()方法时的执行情况)
package com.jason.comfuns.yield;
/**
* 多线程学习
* @function
* @author 小风微凉
* @time 2018-4-21 下午1:53:37
* 总结:
* 当一个线程调用yield(),那么当前运行线程会让出cpu执行权限,供自己其他同优先级别活更高的优先级别的线程抢夺。
* 谁(线程)抢到,谁开始运行。
*/
public class Thread_yield_Action extends Thread{
private String thname;
public Thread_yield_Action(String name){
super(name);
this.thname=name;
}
public void run(){
System.out.println(Thread.currentThread().getName()+"线程运行开始");
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"线程运行:"+i);
if(i==5){//当i为5时,该线程会让出CPU的执行机会,让其他或自己的线程执行。(简单来说:谁抢到CPU的权限谁执行)
System.out.println(Thread.currentThread().getName()+"让出CPU权限-------------");
Thread.yield();//或者this.yield()
}
}
System.out.println(Thread.currentThread().getName()+"线程运行结束");
}
public static void main(String[] args) {
Thread_yield_Action thread1=new Thread_yield_Action("A");
Thread_yield_Action thread2=new Thread_yield_Action("B");
thread1.start();
thread2.start();
}
}
运行结果:
运行结果:(当一个线程执行yield()后就让出cpu执行权限,供其他同优先级或自己的线程竞争抢夺)
B线程运行开始
A线程运行开始
A线程运行:0
A线程运行:1
A线程运行:2
B线程运行:0
A线程运行:3
A线程运行:4
A线程运行:5
A让出CPU权限-------------
B线程运行:1
B线程运行:2
B线程运行:3
B线程运行:4
B线程运行:5
A线程运行:6
A线程运行:7
A线程运行:8
A线程运行:9
B让出CPU权限-------------
A线程运行结束
B线程运行:6
B线程运行:7
B线程运行:8
B线程运行:9
B线程运行结束
简单案例:(测试:2个线程,一个优先级10 , 一个优先级5,让优先级10的线程主动让出CPU的执行权限,检测执行情况)
package com.jason.comfuns.yield;
/**
* 多线程学习
* @function 测试: yield()方法
* @author 小风微凉
* @time 2018-4-21 下午1:53:37
* 总结:
* 当一个线程调用yield(),那么当前运行线程会让出cpu执行权限,供自己其他同优先级别活更高的优先级别的线程抢夺。
* 谁(线程)抢到,谁开始运行。
*/
public class Thread_yield_Action extends Thread{
private String thname;
public Thread_yield_Action(String name){
super(name);
this.thname=name;
}
public void run(){
System.out.println(Thread.currentThread().getName()+"线程运行开始");
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"线程运行:"+i);
if(i==5){//当i为5时,该线程会让出CPU的执行机会,让其他或自己的线程执行。(简单来说:谁抢到CPU的权限谁执行)
if("A".equals(Thread.currentThread().getName())){//如果是优先级大的则yield执行一次退让
System.out.println(Thread.currentThread().getName()+"让出CPU权限-------------");
Thread.yield();//或者this.yield()
}
}
}
System.out.println(Thread.currentThread().getName()+"线程运行结束");
}
public static void main(String[] args) {
Thread_yield_Action thread1=new Thread_yield_Action("A");
Thread_yield_Action thread2=new Thread_yield_Action("B");
thread1.setPriority(MAX_PRIORITY);//优先级:10
thread1.start();
thread2.setPriority(MIN_PRIORITY);//优先级:5
thread2.start();
}
}
运行结果:(总结:A的优先级为10级,B的优先级为5级,即使A的线程调用了yield()方法,让出了cpu的执行权,从执行状态退到了可执行状态,但是由于目前之后线程A和线程B,还是会优先调度线程A)
A线程运行开始
A线程运行:0
A线程运行:1
A线程运行:2
B线程运行开始
A线程运行:3
A线程运行:4
A线程运行:5
A让出CPU权限-------------
B线程运行:0
A线程运行:6
A线程运行:7
A线程运行:8
A线程运行:9
A线程运行结束
B线程运行:1
B线程运行:2
B线程运行:3
B线程运行:4
B线程运行:5
B线程运行:6
B线程运行:7
B线程运行:8
B线程运行:9
B线程运行结束
简单案例:(测试:2个线程,一个优先级10 , 一个优先级5,让优先级5的线程主动让出CPU的执行权限,检测执行情况)
修改上面部分代码:
public static void main(String[] args) {
Thread_yield_Action thread1=new Thread_yield_Action("A");
Thread_yield_Action thread2=new Thread_yield_Action("B");
Thread_yield_Action thread3=new Thread_yield_Action("C");
thread1.setPriority(MIN_PRIORITY);//5级
thread1.start();
thread2.setPriority(MAX_PRIORITY);//10级
thread2.start();
thread3.setPriority(2);//2级
thread3.start();
}
运行结果:(总结:A的优先级为5级,B的优先级为10级,此时由于B的优先级高于A,B已经先行执行完毕了,然后A的线程调用了yield()方法,让出了cpu的执行权,此时只剩下A线程和C线程,由于A线程优先级别高于C线程,则仍然会优先执行A线程,最后C线程)
B线程运行开始
B线程运行:0
B线程运行:1
B线程运行:2
B线程运行:3
B线程运行:4
B线程运行:5
B线程运行:6
B线程运行:7
B线程运行:8
B线程运行:9
B线程运行结束
A线程运行开始
A线程运行:0
A线程运行:1
A线程运行:2
A线程运行:3
A线程运行:4
A线程运行:5
A让出CPU权限-------------
A线程运行:6
A线程运行:7
A线程运行:8
A线程运行:9
A线程运行结束
C线程运行开始
C线程运行:0
C线程运行:1
C线程运行:2
C线程运行:3
C线程运行:4
C线程运行:5
C线程运行:6
C线程运行:7
C线程运行:8
C线程运行:9
C线程运行结束
多线程学习-基础(四)常用函数说明:sleep-join-yield的更多相关文章
- Python学习笔记之常用函数及说明
Python学习笔记之常用函数及说明 俗话说"好记性不如烂笔头",老祖宗们几千年总结出来的东西还是有些道理的,所以,常用的东西也要记下来,不记不知道,一记吓一跳,乖乖,函数咋这么多 ...
- Java多线程学习(四)等待/通知(wait/notify)机制
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79690279 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- 【转】JNI学习积累之一 ---- 常用函数大全
原文网址:http://blog.csdn.net/qinjuning/article/details/7595104 本文原创,转载请注明出处:http://blog.csdn.net/qinjun ...
- C++学习基础十六-- 函数学习笔记
C++ Primer 第七章-函数学习笔记 一步一个脚印.循序渐进的学习. 一.参数传递 每次调用函数时,都会重新创建函数所有的形参,此时所传递的实参将会初始化对应的形参. 「如果形参是非引用类型,则 ...
- 多线程学习-基础(一)Thread和Runnable实现多线程
很久没记录一些技术学习过程了,这周周五的时候偶尔打开“博客园”,忽然让我产生一种重拾记录学习过程的想法,记录下学习研究过程的一点一滴,我相信,慢慢地就进步了!最近想学习一下多线程高并发,但是多线程在实 ...
- 多线程学习-基础(十二)生产者消费者模型:wait(),sleep(),notify()实现
一.多线程模型一:生产者消费者模型 (1)模型图:(从网上找的图,清晰明了) (2)生产者消费者模型原理说明: 这个模型核心是围绕着一个“仓库”的概念,生产者消费者都是围绕着:“仓库”来进行操作, ...
- 多线程学习-基础(六)分析wait()-notify()-notifyAll()
一.理解wait()-notify()-notifyAll()obj.wait()与obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,notify是针对已经获 ...
- JNI学习积累之一 ---- 常用函数大全
主要资料来源: 百度文库的<JNI常用函数> . 同时对其加以了补充 . 要素 :1. 该函数大全是基于C语言方式的,对于C++方式可以直接转换 ,例如,对于生成一个jstring类型的 ...
- javascript学习第四课函数
函数也是一种数据类型:function类型 所以函数也可当作一个数据作参数传递 三种函数的声明示例: 一般来讲,声明方式一和声明方式二比较常用,方式三比较少. 常用函数方式示例: 注意:虽然函数支持嵌 ...
随机推荐
- Greenplum中角色权限及客户端认证管理
角色权限及客户端认证管理 GP数据库逻辑结构 在GP中,Database(数据库).Schema(模式)以及Role(角色)三者之间的关系如下所示: 一个数据库下可以有多个模式,一个模式只属于一个数据 ...
- 安装webpack
首先要安装 Node.js, Node.js 自带了软件包管理器 npm,Webpack 需要 Node.js v0.6 以上支持,建议使用最新版 Node.js. 用 npm 安装 Webpack: ...
- Linux下markdown编辑软件 — retext 支持实时预览,存为pdf、html、ODT等
本文由Suzzz原创,发布于 http://www.cnblogs.com/Suzzz/p/4129368.html,转载请保留此声明 ReText是一个linux下的markdown和reStruc ...
- Kerberos的启动和关闭
Kerberos概念 1.Kerberos用户 Kerberos的本质是维护一套自己的用户:或者说是核心用户映射,比如你的系统用户里面有hdfs,那么我将会在KDC中创建一套基于机器(假设我们有三台安 ...
- 自己写的工具:把Evernote(印象笔记)的笔记导入到博客(Blog)中
Evernote是个强大的工具, 这个伴随了我快4年的工具让我积累好多笔记.但是,如何把evernote(印象笔记)中的笔记发布到博客中呢? 自己空闲时候用python 3写了个工具Evernote2 ...
- Linux应用程序调用其他程序执行
一.system 1.作用 在Linux应用程序中调用另一个程序: 2.用法 system("/sbin/ifconfig"): 二.popen 1.作用 调用另一个程序执行,同时 ...
- 使用jmx4perl和j4psh接管Jolokia
在ActiveMQ的API中,内置了Jolokia . 可以使用jmx4perl来安装: $ perl -MCPAN -e shell Terminal does not support AddHis ...
- 第五章 深入class文件结构(待续)
JVM指令集简介 class文件头的表示形式 常量池 类信息 Fields和Methods定义 类属性描述 Javap生成的class文件结构
- 第七章 Java中的13个原子操作类
当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i = 1:A线程更新i + 1,B线程也更新i + 1,经过两个线程操作之后可能i不等于3,而是等于2,.因为A和B线 ...
- CentOS 7.2 部署Rsync + Lsyncd服务实现文件实时同步/备份 (三)
配置过程中遇到的错误与查看日志 以下错误是在服务正常开启的情况下发生的,请先查看服务是否正常启动. 一.错误 1. rsync: failed to set times on "." ...