多线程学习笔记(四)---- Thread类的其他方法介绍
一、wait和 sleep的区别
- wait可以指定时间也可以不指定时间,而sleep必须指定时间;
- 在同步中时,对cpu的执行权和锁的处理不同;
wait:释放执行权,释放锁;释放锁是为了别人notify
sleep:释放执行权,不释放锁;sleep到时间后,自己醒,不需要别人来叫
二、线程的停止
1、前言
Thread类有stop()方法,但不建议使用。详细情况,看API介绍,已过时并具有安全隐患。
这里采用的是在run()方法里,结束线程。在任务中添加循环结构,只要控制循环就可以结束任务;而控制循环通常就用定义标记来完成。
2、错误代码
//线程任务
public class StopThread implements Runnable{
private boolean flag = true;//为了控制线程任务的结束和开始
public void run(){
while(flag){
System.out.println(Thread.currentThread().getName()+"......");
}
}
//关闭线程任务
public void setFlag(){
flag = false;
}
}
//测试类
public class Doem {
public static void main(String[] args) {
StopThread demo = new StopThread();
Thread test1 = new Thread(demo);
Thread test2 = new Thread(demo);
test1.start();
test2.start();
int num = 1;
for(;;){
if(++num==50){
demo.setFlag();
break;
}
System.out.println("main....."+num);
}
System.out.println("main over");
}
}
- 错误原因
上述代码存在一个安全隐患,即当一个线程处于线程池中,你是无法通过标记来结束任务。
3、隐患详解
(1)隐患展示
//设置多线程,并使该线程进入线程池中
public class StopThread implements Runnable{
private boolean flag = true;//为了控制线程任务的结束和开始
public synchronized void run(){
while(flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"......");
}
}
//关闭线程任务
public void setFlag(){
flag = false;
}
}
//测试
public class Doem {
public static void main(String[] args) {
StopThread demo = new StopThread();
Thread test1 = new Thread(demo);
Thread test2 = new Thread(demo);
test1.start();
test2.start();
int num = 1;
for(;;){
if(++num==50){
demo.setFlag();
break;
}
System.out.println("main....."+num);
}
System.out.println("main over");
}
}
- 现象:该程序并没有结束,因为除了主线程结束,其他线程并没有结束,它们进入线程池中
- 解决思路:当一个线程处于线程池中,我们自然是没办法直接叫它结束任务的,但是,我们可以把它唤醒,然后再叫它结束。
- 解决办法:Thread类的interrupt()方法
将线程从线程池中移到锁池里,让线程具备cpu的执行资格,此时强制动作会抛出InterruptedException异常,记得要处理
4、完善代码
//多线程任务代码
public class StopThread implements Runnable{
private boolean flag = true;//为了控制线程任务的结束和开始
public synchronized void run(){
while(flag){
try {
wait();
} catch (InterruptedException e) {
flag = false;//当interrupt()方法来强制中断时,由标记来结束线程任务
}
System.out.println(Thread.currentThread().getName()+"......");
}
}
//关闭线程任务
public void setFlag(){
flag = false;
}
}
//测试
public class Doem {
public static void main(String[] args) {
StopThread demo = new StopThread();
Thread test1 = new Thread(demo);
Thread test2 = new Thread(demo);
test1.start();
test2.start();
int num = 1;
for(;;){
if(++num==50){
//demo.setFlag();
test1.interrupt();//关闭test1线程
test2.interrupt();//关闭test2线程
break;
}
System.out.println("main....."+num);
}
System.out.println("main over");
}
}
三、void setDaemon(boolean on)
1、作用
- 参数on为true,则将线程标记为守护线程;
- 参数on为false,则将线程标记为用户线程;
- 注意:该方法必须在启动线程前,调用!!!
2、守护线程与用户线程的介绍
- 用户线程的关闭必须程序指定;
- 而守护线程是当所有用户线程都关闭时,守护线程就自动关闭;
- 在其他地方,例如:争取CPU执行权、消耗资源等等,守护线程与用户线程是一样的;
3、举例
public class StopThread implements Runnable{
private boolean flag = true;//为了控制线程任务的结束和开始
public synchronized void run(){
while(flag){
try {
wait();
} catch (InterruptedException e) {
flag = false;//当interrupt()方法来强制中断时,由标记来结束线程任务
}
System.out.println(Thread.currentThread().getName()+"......");
}
}
//关闭线程任务
public void setFlag(){
flag = false;
}
}
public class Doem {
public static void main(String[] args) {
StopThread demo = new StopThread();
Thread test1 = new Thread(demo);
Thread test2 = new Thread(demo);
test1.start();
test2.setDaemon(true);//设置test2线程为守护线程
test2.start();
int num = 1;
for(;;){
if(++num==50){
//demo.setFlag();
test1.interrupt();//关闭test1线程
//test2.interrupt();//test2线程在main、test1线程关闭后,自动关闭
break;
}
System.out.println("main....."+num);
}
System.out.println("main over");
}
}
四、void join()
1、作用
等待该线程终止;
在某个线程调用一个线程的join方法,代表:从此刻被调用join方法的线程为与锁池(即可以争取CPU),而另一个线程则会被放入线程池中。
2、举例
//测试
public class Doem {
public static void main(String[] args) {
Resource demo = new Resource();
Thread test1 = new Thread(demo);
Thread test2 = new Thread(demo);
test1.start();
test1.join();//test1位于锁池中,并且让mian线程位于线程池中
test2.start();
int num = 1;
for(;;){
System.out.println("main....."+num);
}
}
}
这里现象是:线程test1.join()后,只有test1线程在争取CPU的执行权;
public class Doem {
public static void main(String[] args) {
Resource demo = new Resource();
Thread test1 = new Thread(demo);
Thread test2 = new Thread(demo);
test1.start();
test2.start();
test1.join();//test1位于锁池中,并且让mian线程位于线程池中
int num = 1;
for(;;){
System.out.println("main....."+num);
}
}
}
这里现象是:只有主线程位于线程池中,而test1、test2线程位于锁池中争取CPU执行权
五、void setPriority(int newPriority)
1、作用
更改线程的优先级。参数newPriority范围为1-10,其中10最高;
通常有三个常量来方便指定:
- MAX_PRIORITY:最高优先级,10;
- MIN_PRIORITY :最低优先级,1;
- NORM_PRIORITY :默认优先级,5;
六、String toString()
1、作用
返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
多线程学习笔记(四)---- Thread类的其他方法介绍的更多相关文章
- c++11多线程学习笔记之一 thread基础使用
没啥好讲的 c++11 thread类的基本使用 #include "stdafx.h" #include <iostream> #include <thre ...
- 多线程(二)~Thread类相关的API介绍
一.线程安全问题: 当我们使用多个线程操作统一方法内的局部变量的时候,每个局部变量在当前线程里都有自己的副本,这种情况是不会出现线程安全问题的.当我们两个线程同时操作全局变量的时候,有可能 ...
- 多线程学习笔记四之Condition实现分析
目录 简介 等待队列 nextWaiter 源码分析 await() signal() signalAll() 总结 简介 在使用内置锁synchronized时,通过调用java.lang.Ob ...
- ES6学习笔记四(类和对象)
{ // 构造函数和实例 class Parent{ constructor(name='mukewan'){ this.name=name; } } let v_parent=new Parent( ...
- swift学习笔记(四)关于类的继承
在swift中,继承是区分类与其它对象的基本特征 继承后的子类能够重写父类的方法,包含类方法和实例方法,属性和附属脚本(subscript) 在继承过程中,构造器方法init()是不被继承的,须要显示 ...
- Typescript 学习笔记四:回忆ES5 中的类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- 多线程学习笔记六之并发工具类CountDownLatch和CyclicBarrier
目录 简介 CountDownLatch 示例 实现分析 CountDownLatch与Thread.join() CyclicBarrier 实现分析 CountDownLatch和CyclicBa ...
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
- Java多线程学习笔记
进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ...
随机推荐
- SpringCloud第二代实战系列:一文搞定Nacos实现服务注册与发现
一.背景:SpringCloud 生态圈 在正式开始本篇文章之前我们先岔开来讲一下SpringCloud的生态圈. SpringCloud大家都比较熟悉了,它制定了分布式系统的标准规范,做了高度抽象和 ...
- VUE三 vue-router(路由)详解
前端路由 根据不同的 url 地址展示不同的内容或页面,无需依赖服务器根据不同URL进行页面展示操作 优点 用户体验好,不需要每次都从服务器全部获取,快速展现给用户 缺点 使用浏览器的前进,后退键的时 ...
- 编译 openwrt 及初始配置
主机为 ubuntu 14 x64 硬件: 优酷土豆宝 cpuMT7620A,内存128M,flash 32M有2个源,用哪个也可以git clone https://github.com/openw ...
- 基于linux下的NIST数字测试包安装过程
基于linux下的NIST数字测试包安装过程 1. 首先解决windows文件不能粘贴到Ubuntu的问题 选择利用VMware Tools进行解决 打开虚拟机VMware Workstation,启 ...
- 通过locust进行性能测试
首先我们需要准备好python环境 接口 安装python 插件 locust,网上有很多文章而且都很错,这里不再赘述 我是通过pycharm 编写的代码 导入 HttpLocust,TaskSet ...
- oracle中plsql练习题-----编写一个PL/SQL块,输出所有员工的员工姓名、员工号、工资和部门号
一.思路:首先输出需要变量接收,需要声明变量,于是考虑什么变量类型比较合适,在这我用的是table类型,最后,查询出来,循环输出即可. 二.具体实现 -- 编写一个PL/SQL块,输出所有员工的员工姓 ...
- Flutter配置环境报错“PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target”
背景:最近看了很多Flutter漂亮的项目,想要尝试一下.所有环境都搭建好之后,按照文档一步一步配置(抄袭),但始终报如下图错误. PKIX path building failed: sun.sec ...
- 关于CORS(跨域资源共享)的几个http请求头小实验
对几种与跨域相关的请求头做一个总结 关于跨域可以看:9 种常见的前端跨域解决方案(详解) 看完后可以配合我的代码做些实验,看看注释掉某个响应头会发生什么,整体代码会在最后贴出 跨域简单请求 需要在服务 ...
- jquery 获取url携带的参数
url= "/page/employee/employeeUpdate.html?id="+data.id 获取 url携带的参数 -> $.getUrlParam = fu ...
- Unity 游戏框架搭建 2019 (八) 关于导出 UnityPackage 功能的小结
导出 UnityPackage 功能到这里要告一段落了,相信认真看的童鞋都有收获.笔者在写教程之前纠结了很久.到底是先给出一坨工具代码,然后再逐个讲解比较好,还是一篇一个知识点比较好.后来想通了.工具 ...