Java并发编程之Thread类详解

简介: Java并发编程之Thread类详解

Thread类详解:



1.线程(Thread): 是操作系统进行调度的最小单位,Java中的线程是对操作系统线程的封装。本文从线程的创建到停止结合代码和具体实例分析一下关于java线程的一些常见问题。


2.线程的创建:


(1)自己写一个类继承于java.lang.Thread类,并重写run()接口


(2)实现java.lang.Runnable接口,并传给Thread的构造函数。


//方式1
class MyThread extends Thread{
    @Override
    public void run() {
        //to do something in this thread
    }
}
//new一个Thread对象
Thread thread = new MyThread();
//方式2
class MyRunnable implements Runnable{
    @Override
    public void run() {
        //to do something in this thread
    }
}
//new一个线程对象
Thread thread = new Thread(new MyRunnable());


3.线程的启动: 线程对象提供了一个start方法,调用了start方法后,线程将被操作系统调度执行,执行时JVM会调用线程的run方法。值得注意的是:start方法不能重复调用,举个例子


Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("1");
    }
});
for(int i=0;i<10;i++){
    thread.start();
}


image.png


4.线程中断:线程对象提供了一个interrupt方法,可以对一个已经启动的线程进行中断操作。对一个线程执行interrupt操作后,有如下四种结果:


(1)如果被中断的线程正处于阻塞状态:包括阻塞于Object.wait(),Thread.join(),Thread.sleep()等方法,那么该线程将收到一个InterruptedException,同时线程的中断状态将被设置为false;


(2)如果被中断的线程阻塞于java.nio.channels.InterruptibleChannel的IO操作,那么channel将被关闭,并且该线程将的中断状态将被设置为true,同时该线程将收到一个java.nio.channels.ClosedByInterruptException;


(3)如果被中断的线程阻塞于java.nio.channels.Selector,那么阻塞的方法将立即返回,同时线程的中断状态将被设置为true;


(4)如果不是以上3种情况,那么被中断线程的中断状态将被设置为true。


Thread thread1 = new Thread(new Runnable() {
    @Override
    public void run() {
        int i=0;
        //调用interrupt()后,循环会退出吗?答案是肯定会的
        while (!Thread.currentThread().isInterrupted()){
            System.out.println(String.format("线程名称:[%s],执行第:[%s]次循环",Thread.currentThread().getName(),i+1));
            i++;
        }
    }
},"thread1");
thread1.start();
try {
    Thread.sleep(10);
} catch (InterruptedException e) {
    e.printStackTrace();
}
//中断线程
thread1.interrupt();


Thread thread1 = new Thread(new Runnable() {
    @Override
    public void run() {
        int i=0;
        //调用interrupt()后,循环会退出吗?答案是不会
        while (!Thread.currentThread().isInterrupted()){
            System.out.println(String.format("线程名称:[%s],执行第:[%s]次循环",Thread.currentThread().getName(),i+1));
            i++;
            try {
                Thread.sleep(100);//状态会被清理,循环不会终止
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println(String.format("[%s] is interrupted",Thread.currentThread().getName()));
            }
        }
        System.out.println(String.format("线程名称:[%s],执行结束",Thread.currentThread().getName()));
    }
},"thread1");
thread1.start();
try {
    Thread.sleep(10);
} catch (InterruptedException e) {
    e.printStackTrace();
}
thread1.interrupt();


5.线程休眠:Thread.sleep()方法,该方法是让当前线程休息一定的时间后,再继续执行。需要指出的是,在执行该方法后,当前线程并不会释放锁,在高并发的场景下可能会导致其他线程无法获取锁从而造成性能问题,因此要慎用该方法。


6.等待线程执行完毕:在一个线程中等待另一个线程执行完毕,只需要调用线程对象的join()方法即可


Thread thread1 = new Thread(new Runnable() {
    @Override
    public void run() {
        for (int i=0;i<10;i++){
            System.out.println(String.format("线程名称:[%s],执行第:[%s]次循环",Thread.currentThread().getName(),i+1));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
},"thread1");
thread1.start();
try {
    thread1.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
//等thread1执行完毕,才会执行到这里
System.out.println("main thread finished successfully");


7.线程的停止:


当线程的run()方法执行完毕,线程会自然的停止。那么问题来了,怎么让一个运行状态中的线程停止呢?JDK中的Thread提供了一个静态方法stop(),不过目前已经废弃了。因为stop方法在线程停止的同时会让线程释放已经获取的锁,这会导致其他排队等待锁的线程获取锁,从而导致不可预知的情况。所以,官方已经不建议使用Thread.stop()方法了。那么,停止线程的正确姿势是什么?JDK中建议用一个自定义的变量用于标识线程是否需要退出,然后线程不断地去检查该变量从而决定要不要从run方法退出;或者调用线程对象的interrupt方法,通过中断异常来退出执行。


8.线程安全:


共享变量: 多个线程都能访问的变量,通常是静态变量或类的成员变量。为啥这两类变量是共享的啊?因为他们存放在JVM的堆上,JVM堆上的内存区域是多个线程共享的。


目录
相关文章
|
2天前
|
Java
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、&quot;+&quot;操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
|
1天前
|
存储 Java 编译器
课时11:综合实战:简单Java类
本次分享的主题是综合实战:简单 Java 类。主要分为两个部分: 1.简单 Java 类的含义 2.简单 Java 类的开发
|
3天前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
17 5
|
1天前
|
Oracle Java 关系型数据库
课时37:综合实战:数据表与简单Java类映射转换
今天我分享的是数据表与简单 Java 类映射转换,主要分为以下四部分。 1. 映射关系基础 2. 映射步骤方法 3. 项目对象配置 4. 数据获取与调试
|
24天前
|
安全 Java 编译器
JAVA泛型类的使用(二)
接上一篇继续介绍Java泛型的高级特性。3. **编译时类型检查**:尽管运行时发生类型擦除,编译器会在编译阶段进行严格类型检查,并允许通过`extends`关键字对类型参数进行约束,确保类型安全。4. **桥方法**:为保证多态性,编译器会生成桥方法以处理类型擦除带来的问题。5. **运行时获取泛型信息**:虽然泛型信息在运行时被擦除,但可通过反射机制部分恢复这些信息,例如使用`ParameterizedType`来获取泛型参数的实际类型。
|
2天前
|
Java 开发工具
课时6:Java编程起步
课时6:Java编程起步,主讲人李兴华。课程摘要:介绍Java编程的第一个程序“Hello World”,讲解如何使用记事本或EditPlus编写、保存和编译Java源代码(*.java文件),并解释类定义、主方法(public static void main)及屏幕打印(System.out.println)。强调类名与文件名一致的重要性,以及Java程序的编译和执行过程。通过实例演示,帮助初学者掌握Java编程的基本步骤和常见问题。
|
8月前
|
Java 开发者
Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别
Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别
82 0
|
5月前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
82 1
|
Java
Java基础系列-第一章 创建Thread的6种方式和线程常用方法
读完本章节,您将掌握如何创建线程和线程的常用方法。
196 1
Java基础系列-第一章 创建Thread的6种方式和线程常用方法
|
缓存 安全 Java
JAVA Thread Dump分析线程竞争
JAVA Thread Dump分析线程竞争
123 0

热门文章

最新文章