JavaEE语法第二章之多线程(初阶二)

news/2024/11/15 7:24:29/

目录

一、线程常用方法

1.1启动一个线程-start()

1.2中断一个线程

1.2.1使用自定义的变量来作为标志位.

1.2.2使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定义标志位.

1.2.3观察标志位是否清除

1.3等待一个线程-join()

1.4获取当前线程引用

 1.5休眠当前线程

二、线程的状态

2.1观察线程的所有状态

2.2线程状态和状态转移的意义

2.3观察线程的状态和转移

2.3.1关注 NEW 、RUNNABLE 、TERMINATED 状态的转换 

2.3.2关注 WAITING 、BLOCKED 、TIMED_WAITING 状态的转换


一、线程常用方法

1.1启动一个线程-start()

之前我们已经看到了如何通过覆写 run 方法创建一个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。

  • 覆写 run 方法是提供给线程要做的事情的指令清单
  • 线程对象可以认为是把 李四、王五叫过来了
  • 而调用 start() 方法,就是喊一声:”行动起来!“,线程才真正独立去执行了。

 调用 start 方法, 才真的在操作系统的底层创建出一个线程.

1.2中断一个线程

李四一旦进到工作状态,他就会按照行动指南上的步骤去进行工作,不完成是不会结束的。但有时我们需要增加一些机制,例如老板突然来电话了,说转账的对方是个骗子,需要赶紧停止转账,那张三该如何通知李四停止呢?这就涉及到我们的停止线程的方式了。

目前常见的有以下两种方式:
1. 通过共享的标记来进行沟通
2. 调用 interrupt() 方法来通知

1.2.1使用自定义的变量来作为标志位.

public class ThreadDemo9 {//布尔类型成员变量:Lambda表达式进行变量捕获//自定义标志位public static boolean isQuit = false;public static void main(String[] args) {Thread thread =new Thread(()->{while(!isQuit){System.out.println("Hello Thread");try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}}System.out.println("Thread线程终止");});thread.start();//在主线程中修改isQuittry{Thread.sleep(3000);}catch(InterruptedException e){e.printStackTrace();}isQuit=true;}
}

如果将isQuit从成员变量改为局部变量,代码能否正常运行?

不能正常运行。因为变量捕获

1.2.2使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定义标志位.

Thread 内部包含了一个 boolean 类型的变量作为线程是否被中断的标记

public class ThreadDemo10 {public static void main(String[] args) {Thread thread=new Thread(()->{while(!Thread.currentThread().isInterrupted()){//currentThread是获取到当前线程的实例//此处currentThread得到的对象是Thread//isInterrupted是Thread自带的标志位System.out.println("Hello Thread");try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();//手动让其结束break;}}});thread.start();try{Thread.sleep(3000);}catch(InterruptedException e){e.printStackTrace();}//把Thread内部的标志位设置为truethread.interrupt();}
}

thread 收到通知的方式有两种:
1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择忽略这个异常, 也可以跳出循环结束线程.

2. 否则,只是内部的一个中断标志被设置,thread 可以通过Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志

1.2.3观察标志位是否清除

标志位是否清除, 就类似于一个开关.
Thread.isInterrupted() 相当于按下开关, 开关自动弹起来了. 这个称为 "清除标志位"
Thread.currentThread().isInterrupted() 相当于按下开关之后, 开关弹不起来, 这个称为
"不清除标志位".

 

使用 Thread.isInterrupted() , 线程中断会清除标志位.

public class ThreadDemo {private static class MyRunnable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.interrupted());}}}public static void main(String[] args) throws InterruptedException {MyRunnable target = new MyRunnable();Thread thread = new Thread(target, "李四");thread.start();thread.interrupt();}
}

true // 只有一开始是 true,后边都是 false,因为标志位被清
false
false
false
false
false
false
false
false
false 

使用 Thread.currentThread().isInterrupted() , 线程中断标记位不会清除

public class ThreadDemo {private static class MyRunnable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().isInterrupted());}}}public static void main(String[] args) throws InterruptedException {MyRunnable target = new MyRunnable();Thread thread = new Thread(target, "李四");thread.start();thread.interrupt();}
}

 true // 全部是 true,因为标志位没有被清
true
true
true
true
true
true
true
true
true 

1.3等待一个线程-join()

有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作。例如,张三只有等李四转账成功,才决定是否存钱,这时我们需要一个方法明确等待线程的结束。

public class ThreadDemo11 {public static void main(String[] args) {Thread thread =new Thread(()->{System.out.println("Hello Thread");});thread.start();try{thread.join();}catch(InterruptedException e){e.printStackTrace();}System.out.println("Hello Main");}
}

 

  1.4获取当前线程引用

public class ThreadDemo {public static void main(String[] args) {Thread thread = Thread.currentThread();System.out.println(thread.getName());}
}

 1.5休眠当前线程

public class ThreadDemo {public static void main(String[] args) throws InterruptedException {System.out.println(System.currentTimeMillis());Thread.sleep(3 * 1000);System.out.println(System.currentTimeMillis());}
}

二、线程的状态

2.1观察线程的所有状态

线程的状态是一个枚举类型 Thread.State

public class ThreadState {public static void main(String[] args) {for (Thread.State state : Thread.State.values()) {System.out.println(state);}}
}
public class ThreadDemo12 {public static void main(String[] args) throws InterruptedException {Thread thread =new Thread(()->{while(true){try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}}});System.out.println(thread.getState());thread.start();Thread.sleep(2000);System.out.println(thread.getState());}
}
  • NEW: 安排了工作, 还未开始行动
  • RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作.
  • BLOCKED: 这几个都表示排队等着其他事情
  • WAITING: 这几个都表示排队等着其他事情
  • TIMED_WAITING: 这几个都表示排队等着其他事情
  • TERMINATED: 工作完成了.

 2.2线程状态和状态转移的意义

 

还是我们之前的例子:
刚把李四、王五找来,还是给他们在安排任务,没让他们行动起来,就是 NEW 状态;
当李四、王五开始去窗口排队,等待服务,就进入到 RUNNABLE 状态。该状态并不表示已经被银行工作人员开始接待,排在队伍中也是属于该状态,即可被服务的状态,是否开始服务,则看调度器的调度;当李四、王五因为一些事情需要去忙,例如需要填写信息、回家取证件、发呆一会等等时,进入BLOCKED 、WATING 、TIMED_WAITING 状态,至于这些状态的细分,我们以后再详解;如果李四、王五已经忙完,为 TERMINATED 状态。所以,之前我们学过的 isAlive() 方法,可以认为是处于不是 NEW 和 TERMINATED 的状态都是活着的。 

2.3观察线程的状态和转移

2.3.1关注 NEW 、RUNNABLE 、TERMINATED 状态的转换 

public class ThreadStateTransfer {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {for (int i = 0; i < 1000_0000; i++) {}}, "李四");System.out.println(t.getName() + ": " + t.getState());;t.start();while (t.isAlive()) {System.out.println(t.getName() + ": " + t.getState());;}System.out.println(t.getName() + ": " + t.getState());;}
}

2.3.2关注 WAITING 、BLOCKED 、TIMED_WAITING 状态的转换

public static void main(String[] args) {final Object object = new Object();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (object) {while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}}, "t1");t1.start();Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (object) {System.out.println("hehe");}}}, "t2");t2.start();}

使用 jconsole 可以看到 t1 的状态是 TIMED_WAITING , t2 的状态是 BLOCKED

修改上面的代码, 把 t1 中的 sleep 换成 wait

public static void main(String[] args) {final Object object = new Object();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (object) {try {
// [修改这里就可以了!!!!!]
// Thread.sleep(1000);object.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}, "t1");
...}

使用 jconsole 可以看到 t1 的状态是 WAITING

  • BLOCKED 表示等待获取锁, WAITING 和 TIMED_WAITING 表示等待其他线程发来通知.
  • TIMED_WAITING 线程在等待唤醒,但设置了时限; WAITING 线程在无限等待唤醒

http://www.ppmy.cn/news/750551.html

相关文章

java之集合框架的Collecitons工具类

Collections工具类 Collections 是一个操作Set、List、Map等集合的工具类。 Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作&#xff0c; 还提供了对集合对象设置不可变、对结合对象实现同步控制的方法 Collections的常用方法(均为static方法) 排…

初中升高中计算机考试题,初中信息技术中学考试excel操作题.doc

文档介绍&#xff1a; 一、Excel操作题(10分)评委1评委2评委3评委4评委5评委6平均分丽656974598359海林769371679468薛大海497380767375王芳697180855178闽838565708381操作要求:1、给表格加、外边框。(3分)2、添加表格标题“演讲比赛成绩”,并相对表格水平居中;(3分)3、利用公…

初中计算机考试操作题免费,初中信息技术考excel操作题.doc

初中信息技术考excel操作题 一、Excel操作题(10分) 姓名 评委1 评委2 评委3 评委4 评委5 评委6 平均分 魏丽 65 69 74 59 83 59 陈海林 76 93 71 67 94 68 薛大海 49 73 80 76 73 75 王芳 69 71 80 85 51 78 刘闽 83 85 65 70 83 81 操作要求: 1、给表格加内、外边框。(3分) 2…

matlab klobuchar模型,区域似大地水准面精化模型算法的优选

区域似大地水准面精化模型算法的优选 第20卷第1期 2011年2月 ENGINEERING 测 绘 工 程 Vol.20l.1OFSURVEYINGANDMAPPING Feb.,2011 区域似大地水准面精化模型算法的优选 雷伟伟1,张 锋2 (1.河南理工大学测绘与国土信息工程学院,河南焦作454000;2.海军92493部队,辽宁葫芦岛12500…

中科大科学岛计算机博士,2017年科学岛分院博士研究生招生拟录取名单公示

考生编号 姓名 录取专业名称 103587116800027 向皓明 等离子体物理 103587116800028 杨秀达 等离子体物理 103587116800029 钱玉忠 等离子体物理 103587116800030 张超 核能科学与工程 103587116800032 郑瓛 等离子体物理 103587116800033 张睿博 等离子体物理 103587116800034…

DevExpress中使用GridControl控件实现表格(界面拖拽布局)

一、实现效果 GridControl控件实现表格整体功能工程下载 ①实现数据加载到表格界面且自动编写序号,自带的分页功能,单行点击获取改行数据信息界面: ②实现自定义分页效果【把所有数据都提供给DataSource,根据参数配置,设置(每页显示行数)的分页效果】界面。 ③可以导出…

学习Python的第四天

字符串操作 # 切分字符串 language "Python and Java and C and Golang and Scala" # split 切割字符串 生成一个列表&#xff1a; 暂时理解为一个容器 有序序列 result1 language.split("and") print(result1)# 连接序列 生成字符串 跟split 是相反的操…

入门Python基础第四天

1.切分字符串 split()&#xff1a;按照指定字符分割字符串 语法&#xff1a;字符串序列.split(分割字符, num) # 切分字符串 language "Python and java C AND GOlang and Scala"# split 切割字符串 生成一个列表 &#xff1a; 暂时理解为一个容器 有序序列 result…