线程的方法(未完成)

2023-09-17 23:36:27

线程的方法

1.获取当前线程对象:CurrentThread()

    @Test
    public void bb()  {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());//打印  main
    }

2.currentThread().setName和currentThread().getName

    @Test
    public void bb()  {
        Thread.currentThread().setName("heihei");
        String name = Thread.currentThread().getName();
        System.out.println(name); // 打印 heihei
    }

3.currentThread().isAlive()

判断当前线程是否正在执行

    @Test
    public void bb()  {
        MyThread mt = new MyThread() ;    // 实例化Runnable子类对象
        Thread t = new Thread(mt,"线程");        // 实例化Thread对象
        System.out.println("线程开始执行之前 --> " + t.isAlive()) ;     // 打印结果:线程开始执行之前 --> false
        t.start() ;    // 启动线程
        System.out.println("线程开始执行之后 --> " + t.isAlive()) ;     // 打印结果:线程开始执行之前 --> true
    }

4.start()与run()

调用start()方法才是 启动一个新的线程。

调用run()方法只是主线程调用了一个类的一个普通方法.并没有开启一个新线程.

    @Test
    public void bb()  {
        MyThread myThread = new MyThread();
        myThread.start();  //打印  Thread-2运行了
        myThread.run();  //打印   main方法运行了
    }

5.join()/join(long millis)

将两个线程绑定在一起,看成是共同体,B线程执行完成后,必然执行A线程.

join()就是A无限期等待,当B线程执行完,A线程才执行

join(1000)就是A只等待1000毫秒

如果B 500毫秒执行完了,那么 A就直接结束等待时间,直接被唤醒

如果A等待1000毫秒后,B还没执行完,那A也不等了,就直接被唤醒和B一块并发执行

底层其实就是A线程被wait,下面是底层代码

public final synchronized void join(long millis)
throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
        while (isAlive()) {//只要B线程还没结束,A线程就会一直阻塞
            wait(0);//这里的wait调用的本地方法。
        }
    } else {//等待一段指定的时间
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

下面是例子

    @Test
    public void bb()  {
        MyBThread myThread = new MyBThread();
        myThread.start();
        for (int i = 0; i < 15; i++) {
            if(i>5){
                try{
                    myThread.join() ;    // 线程强制运行
                }catch(InterruptedException e){}
            }
            System.out.println("Main线程运行 --> " + i) ;
        }
    }

}
class MyBThread extends Thread{
    @Override
    public void run(){
        for (int i = 0; i < 15; i++) {
            System.out.println(Thread.currentThread().getName()+"运行了,i="+i);
        }

    }
}
Main线程运行 --> 0
Main线程运行 --> 1
Main线程运行 --> 2
Main线程运行 --> 3
Main线程运行 --> 4
Main线程运行 --> 5
Thread-2运行了,i=0
Thread-2运行了,i=1
Thread-2运行了,i=2
Thread-2运行了,i=3
Thread-2运行了,i=4
Thread-2运行了,i=5
Thread-2运行了,i=6
Thread-2运行了,i=7
Thread-2运行了,i=8
Thread-2运行了,i=9
Thread-2运行了,i=10
Thread-2运行了,i=11
Thread-2运行了,i=12
Thread-2运行了,i=13
Thread-2运行了,i=14
Main线程运行 --> 6
Main线程运行 --> 7
Main线程运行 --> 8
Main线程运行 --> 9
Main线程运行 --> 10
Main线程运行 --> 11
Main线程运行 --> 12
Main线程运行 --> 13
Main线程运行 --> 14

6.yield()

yield() 暂停当前方法,释放自己拥有的CPU,线程进入就绪状态。它能让当前线程由“运行状态”进入到“就绪状态”,然后和其他优先级比它高的或者和它相同的线程一起去重新争抢cpu的使用.

优先级高的线程抢到cpu的概率较大,但是不一定会第一个抢到,  因为这还和操作系统的调度和cpu的执行有关系.  建议少用.

7.sleep(long millis)

线程休眠:让执行的线程暂停一段时间,进入计时等待状态。
static void sleep(long millis):调用此方法后,当前线程放弃 CPU 资源,在指定的时间内,sleep 所在的线程不会获得可运行的机会,此状态下的线程不会释放同步锁。
该方法更多的是用来模拟网络延迟,让多线程并发访问同一资源时的错误效果更加明显。

8.wait()和notify()/notifyAll()

wait()/wait(long timeout)/wait(long timeout, int nanos)

先看一看wait的三个重载方法

  • public final void wait() throws InterruptedException
  • public final void wait(long timeout) throws InterruptedException
  • public final void wait(long timeout, int nanos) throws InterruptedException

方法参数

timeout - 等待时间(以毫秒为单位)。

nanos - 额外等待时间(以纳秒为单位)。

wait()相当于调用wait(0),0表示永远不超时。让当前线程处于等待状态,只有调用对象的notify或者notifyAll才能将其唤醒.

wait(1000):等待1000毫秒, 让当前线程处于计时等待状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过参数 timeout设置的超时时间才能将其唤醒.

wait(1000,50):等待1000毫秒+50纳秒, 让当前线程处于计时等待状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过参数 timeout 加上 nanos 设置的超时时间才能将其唤醒.

notify()/notifyAll()

唤醒:notify()-随机唤醒wait的一个线程,notifyAll()-唤醒所有线程
注意:此方法需和wait()成对使用,必须在同步代码块或同步方法中

上面的方法必须在同步代码块或同步方法中

每一个对象都有一个跟它关联的monitor,只有获取到对象的monitor才能调用对象的wait方法和调用对象的notify和notifyAll方法。也就是说wait,notify,notifyAll都必须在对象的synchronized同步方法里面调用。如果wait没有在对象的synchronized同步块里面执行会抛出

java.lang.IllegalMonitorStateException

 结束线程的方法

1.线程正常自动结束

2.使用标准位终结线程

一般 run()方法执行完,线程就会正常结束,然而,常常有些线程是伺服线程。它们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如: 最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while 循环是否退出,代码示例:

@RestController
@RequestMapping("/test")
public class Docx4jOfficeFileToPDF {
        public static void main(String args[]) throws InterruptedException {
            MyBThread mt = new MyBThread() ;
            mt.start();
            Thread.sleep(1);//主线程等待1ms
            mt.exit = true; //修改标志位,退出线程
        }
}
class MyBThread extends Thread{
    //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
    public volatile boolean exit = false;
    @Override
    public void run() {
        int i =1;
        while(!exit){
            System.out.println(i++);
        }
        System.out.println("结束");
    }
}

定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit 时,使用了一个 Java 关键字 volatile,这个关键字的目的是使 exit 同步,也就是说在同一时刻只 能由一个线程来修改exit的值。 

 3.interrupt()

 interrupt() 方法仅仅是在当前线程中打一个停止的标记,并不是真的停止线程。

需要明确的一点的是:interrupt() 方法并不像在 for 循环语句中使用 break 语句那样干脆,马上就停止循环。而是通知目标线程,有人希望你终止。至于目标线程收到通知后会如何处理,则完全由目标线程自行决定。

下面是经常和interrupt()配合的两个方法. 

public boolean Thread.isInterrupted() //判断是否被中断
public static boolean Thread.interrupted() //判断是否被中断,并清除当前中断状态

如使用了 sleep,同步锁的 wait,socket 中的 receiver,accept 等方法时, 会使线程处于阻塞状态。当sleep()等方法和interrupt() 方法相遇时.sleep()等方法会抛出 InterruptException 异常,并清除掉线程的中断标识.

实验得知:

1.在线程sleep()阻塞的时候, 线程再去调 interrupt()方法,会抛出 InterruptException 异常

2.在线程调完interrupt()方法,有中断标识的时候,  线程再去调sleep()方法.也会抛出InterruptException 异常

因此,实验得出下面的代码100%能结束线程.

public class Docx4jOfficeFileToPDF {
    public static void main(String args[]) throws InterruptedException {
        MyBThread mt = new MyBThread() ;
        mt.start();//子线程执行
        mt.interrupt();//给子线程加上中断标志

    }
}
class MyBThread extends Thread{
    @Override
    public void run() {
        while (true){
            try{
                Thread.sleep(500000);//阻塞过程捕获中断异常来退出
            }catch(InterruptedException e){
                e.printStackTrace();
                break;//捕获到异常之后,执行break跳出循环,相当于结束子线程
            }
        }
    }
}

 4.stop ()

此方法已被弃用,不安全.

为什么弃用stop:

  1. 调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。
  2. 调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。
  3. stop()方法被try-catch()后会失效.

例如,存在一个对象 u 持有 ID 和 NAME 两个字段,假如写入线程在写对象的过程中,只完成了对 ID 的赋值,但没来得及为 NAME 赋值,就被 stop() 导致锁被释放,那么当读取线程得到锁之后再去读取对象 u 的 ID 和 Name 时,就会出现数据不一致的问题

@RestController
@RequestMapping("/test")
public class Docx4jOfficeFileToPDF {
        public static void main(String args[]){
            MyBThread mt = new MyBThread() ;
            mt.start();
        }
}
class MyBThread extends Thread{
    @Override
    public void run(){
        System.out.println("运行了111");
        this.stop();
        System.out.println("运行了222");
    }
}
运行了111

更多推荐

Go语言开发环境搭建指南:快速上手构建高效的Go开发环境

Go官网:https://go.dev/dl/Go语言中文网:https://studygolang.com/dl下载Go的语言包进入官方网站Go官网或Go语言中文网:选择下载对应操作系统的安装包:等待下载完成:安装Go的语言包双击运行上一步下载好的Go语言包,点击【Next】:勾选【Iacceptthetermsin

深入了解接口测试:方法、工具和关键考虑因素(一)

接口测试是软件测试中的一项重要工作,它涉及到系统与系统之间的交互点。接口可以是外部接口,也可以是内部接口,包括上层服务与下层服务接口以及同级接口。在接口测试中,我们需要确保接口能够按照预期的方式进行通信和交互,并且能够正确处理输入和输出数据。什么是接口?接口是具有特定输入和输出的一套逻辑处理单元,它不需要了解内部的实现

蓝牙核心规范(V5.4)10.7-BLE 入门笔记之L2CAP

1.概述ATT属性用于两个设备,一个扮演客户端的角色,另一个扮演服务器的角色。服务器公开一系列称为属性的复合数据项。这些属性由服务器按索引列表组织在称为属性表的列表中。每个属性包含一个句柄、一个通用唯一标识符(UUID)、一个值和一组权限。句柄是一个唯一的索引值,ATT客户端可以使用该值来引用属性表中的特定条目。UUI

四川百幕晟科技:提升店铺质量方法是什么?

抖店是抖音旗下的移动电子商务平台,为商家提供在线销售和促销的机会。在抖店,经验值是商家评价和信誉的重要指标之一。反映了平台上商户的服务质量和用户满意度。那么,如何查看自己在抖店手机上的体验分数呢?1、如何查看抖店手机的体验分?1、打开抖音APP:首先,商户需要打开抖音手机APP,登录抖音账号。2.进入“我的”页面:在抖

李开复:我家的AI是坠吼的

创新工场董事长、鸿海独立董事李开复,近日出席鸿海股东会暨媒体记者会时表示,人工智能(AI)是人类史上即将面临的最伟大技术革命,未来十年的改变将改写人类历史、重构所有产业,其发展大致可分三阶段,并看好鸿海在当中软硬件整合方面的优势,非常有机会成为AI相关领域顶尖领导者。李开复所提到的AI发展三阶段,第一波是纯软件将大数据

SpringMVC之JSON返回&异常处理机制

目录一.JSON1.1.介绍1.2.SpringMVC之JSON数据返回1.2.1.导入依赖1.2.2.配置spring-mvc.xml1.2.3.@ResponseBody注解使用1.2.4.常用注解二.统一异常处理2.1.为什么要全局异常处理2.2.异常处理思路2.2.异常处理方式一2.3.异常处理方式二2.4.异

驱动开发--汇总

一,【驱动相关概念】1,什么是驱动能够驱使硬件实现特定功能的软件代码根据驱动程序是否依赖于系统内核将驱动分为裸机驱动和系统驱动2,逻辑驱动和系统驱动的区别裸机驱动:编写的驱动代码中没有进行任何内核相关API的调用,开发者自己配置寄存器完成了相关硬件控制的代码编写。裸机驱动不依赖于系统内核,由开发者独立即可完成,但是裸机

【Vue】轻松理解数据代理

hello,我是小索奇,精心制作的Vue教程持续更新哈,想要学习&巩固&避坑就一起学习叭~Object定义配置方法代码引出数据代理,先上代码,后加解释<!DOCTYPEhtml><html><head><metacharset="UTF-8"/><title>回顾Object.defineproperty方法</tit

Python程序设计实例 | 学生管理数据库系统的开发

本文将通过一个学生管理数据库系统的开发过程来展示如何系统地基于Python实现SQLite数据库编程。以下首先提出数据库系统的基本结构,以及如何通过SQLite逐步达到这些要求并进行常规操作。01、数据表结构该学生管理数据库系统包括4张表:专业表、学生表、课程表和成绩表,用于实现对专业信息、学生信息、课程信息和成绩的综

视频监控系统/安防监控/视频AI智能分析网关:持刀检测算法场景汇总

TSINGSEE青犀AI智能分析网关——持刀检测算法,是一种利用计算机AI分析算法技术来检测和辨别视频中是否存在刀具的算法,用来保障群众安全,维护公共治安,还可以与“人员跌倒”、“人员聚集”、“人员跌倒”等算法结合,制定一体化的安全监管体系,可以应用于各种场景,主要包括以下几个方面:1、公共安全在公共场所,如机场、车站

课程29:.Net Core API限流

🚀前言本文是《.NetCore从零学习搭建权限管理系统》教程专栏的课程(点击链接,跳转到专栏主页,欢迎订阅,持续更新…)专栏介绍:以实战为线索,基于.Net7+REST+Vue、前后端分离,不依赖任何第三方框架,从零一步一步讲解权限管理系统搭建。专栏适用于人群:Web后端开发人员本课程内容:本课程内容:1、API限流

热文推荐