Java多线程常用方法的使用
Java多线程的常用方法基本分为:获取当前线程的操作,线程休眠sleep()方法,线程让步yield()方法,等待其他线程终止join()方法,线程停止的一系列方法。
一、获取当前线程的操作
1、获取当前线程: Thread.currentThread();
需要注意的是: 当一个线程A开启后,调用其他线程类B的普通方法时,此时的线程还是线程A, 当一个线程A直接调用另一个线程类B的run()方法,就和调用普通方法没有区别。
举个栗子说明run()和start()有十分明显的区别
package com.xiaoaxiao.test.thread_test.book_test;
/**
* Created by xiaoaxiao on 2019/7/16
* Description: run()和start()不一样!!!
*/
class MyThread1 extends Thread{
@Override
public void run() {
try {
System.out.println("run threadName="+Thread.currentThread().getName()+" begin");
Thread.sleep(2000);
System.out.println("run threadName="+Thread.currentThread().getName()+" end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadTest2 {
public static void main(String[] args) {
MyThread1 mt = new MyThread1();
System.out.println("begin ="+System.currentTimeMillis());
// mt.run();
mt.start();
System.out.println("end ="+System.currentTimeMillis());
}
}
若调用mt.run(),输出结果为:
begin =1563329164153
run threadName=main begin
run threadName=main end
end =1563329166155
若调用mt.start(),输出结果为:
begin =1563329194123
end =1563329194124
run threadName=Thread-0 begin
run threadName=Thread-0 end
2、获取当前线程的名字:Thread.currentThread().getName()
而获取当前对象的名字(只在Thread的继承类中出现):this.getName()
3、获取当前线程的唯一标识:Thread.currentThread().getId()
二、线程休眠sleep()方法—单位为毫秒(ms)
线程休眠是指 让当前线程暂缓执行,等到了预计时间后再恢复执行。线程休眠会立即交出CPU,但是不会释放锁。
sleep()的流程:运行状态->sleep()->阻塞状态->sleep()的时间结束后->就绪状态->系统调度->运行状态。
虽然sleep()在指定时间可以从运行状态->(阻塞状态)->就绪状态,但是处于就绪状态时,需要经过系统的调度才能到达运行状态,具体的系统调度是随机的(由CPU进行控制),这就导致了每次sleep()的时间不相同(是有差异的)。
sleep()可能会抛出InterruptedException受查异常,需要对异常进行处理。
sleep()立即交出CPU,不会释放锁。
举个栗子
package com.xiaoaxiao.test.thread_test;
/**
* Created by xiaoaxiao on 2019/7/12
* Description: 测试thread常用的方法——sleep、
*/
class MyRunnable2 implements Runnable{
@Override
public void run() {
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName());
// sleep()
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class threadMethodTest1 {
public static void main(String[] args) {
MyRunnable2 myRunnable2 = new MyRunnable2();
Thread thread1 = new Thread(myRunnable2,"A");
// Thread thread2 = new Thread(myRunnable2,"hello");
Thread thread2 = new Thread(myRunnable2,"B");
Thread thread3 = new Thread(myRunnable2,"C");
thread1.start();
thread2.start();
thread3.start();
}
}
输出结果:
B
C
A
A
C
B
B
C
A
三、线程让步yield()方法——运行态(running)->就绪态(runnable)
线程让步是指 暂停执行当前的线程对象,并执行其他线程,yield()方法会让当前线程交出CPU(不一定立即交出CPU),不会释放锁。
yield()方法无法控制具体交出CPU的时间,并且yield()方法只能让拥有相同优先级的线程有获取CPU的机会
yield()会交出CPU(不一定立即交出),不会释放锁。
举个栗子
package com.xiaoaxiao.test.thread_test;
/**
* Created by xiaoaxiao on 2019/7/12
* Description: 测试thread常用的方法——yield
*/
class MyRunnable2 implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName());
// yield()
Thread.yield();
}
}
}
public class threadMethodTest1 {
public static void main(String[] args) {
MyRunnable2 myRunnable2 = new MyRunnable2();
Thread thread1 = new Thread(myRunnable2,"A");
Thread thread2 = new Thread(myRunnable2,"B");
Thread thread3 = new Thread(myRunnable2,"C");
thread1.start();
thread2.start();
thread3.start();
}
}
输出结果:
A
A
A
B
B
C
C
C
B
四、等待其他线程终止join()方法
等待其他线程终止是指主线程等待子线程执行完成之后再结束。(主线程(或者某个线程)中若调用了子线程(或者是另外一个线程)的join()方法就必须得等该子线程run()方法结束,主线程才能继续执行)
join()方法只是对外汇代理Object提供的wait()做了一层包装而已。 (join在内部使用wait()方法进行等待),执行wait(long)方法后,当前线程的锁会被释放,其他线程就可以调用此线程中的同步方法了。
join()方法的执行流程与sleep()类似:运行状态->join()->阻塞状态->join()中断->就绪状态->系统调度->运行状态。
join()可能会抛出InterruptedException受查异常,需要对异常进行处理。
join()会释放锁。
举个栗子
package com.xiaoaxiao.test.thread_test;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by xiaoaxiao on 2019/7/12
* Description: 测试thread常用的方法——join
*/
class MyRunnable3 implements Runnable{
@Override
public void run() {
try {
System.out.println("主线程睡眠前时间");
threadMethodTest2.printTime();
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());
System.out.println("睡眠结束时间");
threadMethodTest2.printTime();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class threadMethodTest2 {
public static void main(String[] args) throws InterruptedException {
MyRunnable3 myRunnable3 = new MyRunnable3();
Thread threadA = new Thread(myRunnable3,"子线程A");
System.out.println("代码开始");
threadA.start();
// 调用子线程的join方法,当主线程执行到这一步了,
// 一定会等到子线程中所有内容全部执行完,主线程才会继续往下执行
threadA.join();
System.out.println(Thread.currentThread().getName());
System.out.println("代码结束");
}
public static void printTime(){
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date);
System.out.println(time);
}
}
输出结果为:
代码开始
主线程睡眠前时间
2019-09-27 16:56:26
子线程A
睡眠结束时间
2019-09-27 16:56:27
main
代码结束
还可以使用join(long)设置最长等待时间(单位:ms),若主线程等待long秒后,无论子线程会不会结束,此时join()中断,主线程进入就绪状态。
class Join extends Thread{
@Override
public void run() {
try {
System.out.println("begin Timer="+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("end Timer="+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class JoinTest {
public static void main(String[] args) {
Thread thread = new Join();
thread.start();
try {
thread.join(2000);
System.out.println("main end Timer:"+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 打印结果
begin Timer=1569575039934
end Timer=1569575041934
main end Timer:1569575041934
五、线程停止的一系列方法
1、设置标记位(flag)停止线程——推荐(好写)
在线程类内部设置一个标记位flag并由这个flag对线程类的执行进行控制,在线程类的外部对flag进行修改,从而实现外部对类内部的停止。
package com.xiaoaxiao.test.thread_test;
/**
* Created by xiaoaxiao on 2019/7/12
* Description: 测试thread常用的方法——线程停止-设置标记符
*/
class MyRunnable4 implements Runnable{
// 设置一个标记符
private Boolean flag = true;
@Override
public void run() {
int i=1;
// 将该标记符当做线程持续进行的条件
while (flag){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("这是第"+i+"次执行"+"线程名称为:"
+Thread.currentThread().getName());
i++;
}
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
}
public class threadMethodTest3 {
public static void main(String[] args) throws InterruptedException {
MyRunnable4 myRunnable4 = new MyRunnable4();
Thread thread = new Thread(myRunnable4);
thread.start();
Thread.sleep(5000);
// 主线程睡眠5s后将flag设置为false,
// 当子线程再次访问是,flag已经变为false
myRunnable4.setFlag(false);
// 调用子线程的join,让主线程等待子线程执行完成后再执行
thread.join();
System.out.println("代码结束");
}
}
2、调用Thread类的stop()方法强制停止线程,该方法不安全,已经被Deprecated(废弃)了。
该方法之所以不安全主要是会造成数据的不一致。
while(flag){ //按照第一种停止方式,即便在x=3后,flag变为了false,
//y依旧能被赋值为4
x=3;
y=4;
} //而如果在x=3后直接stop(),则y就不会被赋值为4了
3、调用Thread类的interrupt()方法——系统设置标志位
①interrupt()方法只是将线程状态置为中断状态而已,它不会中断一个正在运行的线程,此方法只是给线程传递一个中断信号,程序可以根据此信号来判断是否需要终止。(使用isInterrupted()判断中断状态)
②当线程中使用wait()、sleep()、join()导致此线程阻塞,则interrupt()会在线程中抛出InterruptException,并且将线程的中断状态由true置为false。
PS:无论是在sleep()过程中,interrupt(),还是在interrupt()过程中,sleep(),都会抛出InterruptedException异常,并将interrupt中断状态置为false(sleep()和interrupt只要相遇就会出异常,其他两者同理)
③interrupt()中断线程
a)线程中没有wait(),sleep(),join(),调用interrupt只是将线程中断状态设置为true。
b)线程中有wait(),sleep(),join(),调用interrupt会抛出InterruptException并将线程中断状态由true置为false,在catch块中捕获该异常,然后退出
举个栗子,sleep()对interrupt()的影响
package com.xiaoaxiao.test.thread_test.book_test;
/**
* Created by xiaoaxiao on 2019/7/16
* Description: sleep()对Interrupt()的影响
* 无论是在sleep()过程中,interrupt()
* 还是在interrupt()过程中,sleep()
* 都会抛出InterruptedException异常,并将interrupt状态置为false
*/
class MyThread2 extends Thread{
@Override
public void run() {
super.run();
try {
for(int i=0;i<1000000;i++){
System.out.println("i="+(i+1));
}
System.out.println("run begin");
Thread.sleep(200000);
System.out.println("run end");
} catch (InterruptedException e) {
System.out.println("先停止,再遇到sleep,interrupt状态为:"
+this.isInterrupted());
e.printStackTrace();
}
}
}
public class InterruptTest {
public static void main(String[] args) {
MyThread2 mt = new MyThread2();
mt.start();
mt.interrupt();
System.out.println("end!");
}
}
————————————————
原文链接:https://blog.csdn.net/weixin_43490440/article/details/96202420
Java多线程常用方法的使用的更多相关文章
- Java多线程中的常用方法
本文将带你讲诉Java多线程中的常用方法 Java多线程中的常用方法有如下几个 start,run,sleep,wait,notify,notifyAll,join,isAlive,current ...
- Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗
在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...
- Java多线程干货系列—(一)Java多线程基础
前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...
- Java多线程总结之线程安全队列Queue
在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列.Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非 ...
- Java多线程干货系列(1):Java多线程基础
原文出处: 嘟嘟MD 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程 ...
- Java多线程学习(转载)
Java多线程学习(转载) 时间:2015-03-14 13:53:14 阅读:137413 评论:4 收藏:3 [点我收藏+] 转载 :http://blog ...
- Java多线程编程详解
转自:http://programming.iteye.com/blog/158568 线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Ja ...
- [转]Java多线程干货系列—(一)Java多线程基础
Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...
- 【转】 Java 多线程之一
转自 Java 多线程 并发编程 一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进 ...
随机推荐
- #2560异或和问题 jdfz集训—秦岳
题目描述 N个数字,要求选择M次,每次从N个数中选出两个数(Ai,Aj)(但不能和之前某次选择相同),此次选择的得分为Ai xor Aj. 求最大得分. 输入格式 第一行包含两个整数N,M 接下来一行 ...
- jQuery 实现表格变色效果
html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...
- 13.volatile与synchronized比较
synchronized,volatile都解决了共享变量 value 的内存可见性问题,但是前者是独占锁,同时只能有一个线程调用 get()方法,其他调用线程会被阻塞, 同时会存在线程上下文切换和线 ...
- 模板方法模式TemplateMethod
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11407071.html 1. 定义定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子 ...
- 观察者模式Observer
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11409319.html 1. 定义定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依 ...
- Ceph的正确玩法之Ceph纠删码理论与实践
http://blog.itpub.net/31545808/viewspace-2637083/ 注意空格,有的命令少空格 随着云计算业务的快速发展,国内外云计算企业的专利之争也愈发激烈.在云计算这 ...
- linux-usb软件系统架构
1.软件系统架构 USB主控制器,芯片里面自带了得.为了让USB主控制器运行,所有有USB主控制器驱动. USB核心,内核提供好的USB协议之类的.USB设备驱动是针对插到接口的设备去工作的软件. 主 ...
- 后端优化(2)—— BA与图优化
- echarts绘制饼图时的一点特殊设置
最后的效果如图,需要在中间展示的部分换行然后字体大小不同. 以下为option的设置,使用rich里面的参数来设置更多的文本样式,使用‘\n’来控制换行 let option = { color: c ...
- 【C#、阿里云、Tomcat、XP系统】c#下使用.NET4.0中HttpWebRequest访问Tomcat中HTTPS项目时,在XP系统中超时
情景: 1.使用Java开发的Web项目,部署在服务器Tomcat中 2.项目使用HTTPS,使用阿里云的PFX证书 阿里云推荐Tomcat配置如下 <Connector port=" ...