一、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类的其他方法介绍的更多相关文章

  1. c++11多线程学习笔记之一 thread基础使用

    没啥好讲的  c++11  thread类的基本使用 #include "stdafx.h" #include <iostream> #include <thre ...

  2. 多线程(二)~Thread类相关的API介绍

      一.线程安全问题:     当我们使用多个线程操作统一方法内的局部变量的时候,每个局部变量在当前线程里都有自己的副本,这种情况是不会出现线程安全问题的.当我们两个线程同时操作全局变量的时候,有可能 ...

  3. 多线程学习笔记四之Condition实现分析

    目录 简介 等待队列 nextWaiter 源码分析 await() signal() signalAll() 总结 简介   在使用内置锁synchronized时,通过调用java.lang.Ob ...

  4. ES6学习笔记四(类和对象)

    { // 构造函数和实例 class Parent{ constructor(name='mukewan'){ this.name=name; } } let v_parent=new Parent( ...

  5. swift学习笔记(四)关于类的继承

    在swift中,继承是区分类与其它对象的基本特征 继承后的子类能够重写父类的方法,包含类方法和实例方法,属性和附属脚本(subscript) 在继承过程中,构造器方法init()是不被继承的,须要显示 ...

  6. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. 多线程学习笔记六之并发工具类CountDownLatch和CyclicBarrier

    目录 简介 CountDownLatch 示例 实现分析 CountDownLatch与Thread.join() CyclicBarrier 实现分析 CountDownLatch和CyclicBa ...

  8. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

  9. Java多线程学习笔记

    进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ...

随机推荐

  1. javascript入门进阶(一)

    javascript 入门进阶 这里主要讲解一下在入门阶段很难注意的一些知识点,不一定有用.但是会了总比不会强. 1.HTML为<script>标签准备的6个属性: -async:可选.表 ...

  2. Vue2.0 【第一季】第2节 v-if v-else v-show 指令

    目录 Vue2.0 [第一季]第2节 v-if v-else v-show 指令 第二节 v-if v-else v-show 指令 2.1 v-if指令.v-else指令: 2.2 v-show的使 ...

  3. Mac OS X 10.13上 安装odoo 11.0开发环境

    0.准备假设homebrew已经安装好没安装的需要先安装,见下面链接http://brew.sh/ 1.安装PostgreSQL$ brew tap homebrew/services$ brew i ...

  4. 吐血干货,直播首屏耗时400ms以下的优化实践

    导读: 直播行业的竞争越来越激烈,进过18年这波洗牌后,已经度过了蛮荒暴力期,剩下的都是在不断追求体验.最近在帮做直播优化首开,通过多种方案并行,把首开降到500ms以下,希望能对大家有借鉴. 背景: ...

  5. 一文搞懂 Elasticsearch 之 Mapping

    这篇文章主要介绍 Mapping.Dynamic Mapping 以及 ElasticSearch 是如何自动判断字段的类型,同时介绍 Mapping 的相关参数设置. 首先来看下什么是 Mappin ...

  6. (转)ARM GNU常用汇编语言介绍

    ARM GNU常用汇编语言介绍 原文地址:http://zqwt.012.blog.163.com/blog/static/120446842010445441611/ ARM汇编语言源程序语句,一般 ...

  7. Java多线程并发07——锁在Java中的实现

    上一篇文章中,我们已经介绍过了各种锁,让各位对锁有了一定的了解.接下来将为各位介绍锁在Java中的实现.关注我的公众号「Java面典」了解更多 Java 相关知识点. 在 Java 中主要通过使用sy ...

  8. Dapper解析嵌套的多层实体类

    在作项目的时候,我会将一些不涉及查询的字段,形成JSON统一存放在一个字段中,向下面这样的来建实体类, public class WechatModel { public string wechati ...

  9. IdentityServer4源码解析_4_令牌发放接口

    目录 identityserver4源码解析_1_项目结构 identityserver4源码解析_2_元数据接口 identityserver4源码解析_3_认证接口 identityserver4 ...

  10. Salesforce LWC学习(十四) Continuation进行异步callout获取数据

    本篇参考: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_continua ...