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堆上的内存区域是多个线程共享的。


目录
相关文章
|
9天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
14天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
5天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
|
8天前
|
Java 开发者
Java多线程编程的艺术与实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的技术文档,本文以实战为导向,通过生动的实例和详尽的代码解析,引领读者领略多线程编程的魅力,掌握其在提升应用性能、优化资源利用方面的关键作用。无论你是Java初学者还是有一定经验的开发者,本文都将为你打开多线程编程的新视角。 ####
|
7天前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
10天前
|
安全 Java 开发者
Java多线程编程中的常见问题与解决方案
本文深入探讨了Java多线程编程中常见的问题,包括线程安全问题、死锁、竞态条件等,并提供了相应的解决策略。文章首先介绍了多线程的基础知识,随后详细分析了每个问题的产生原因和典型场景,最后提出了实用的解决方案,旨在帮助开发者提高多线程程序的稳定性和性能。
|
13天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
14天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
5月前
|
Java C++
关于《Java并发编程之线程池十八问》的补充内容
【6月更文挑战第6天】关于《Java并发编程之线程池十八问》的补充内容
49 5
|
2月前
|
缓存 监控 Java
Java中的并发编程:理解并应用线程池
在Java的并发编程中,线程池是提高应用程序性能的关键工具。本文将深入探讨如何有效利用线程池来管理资源、提升效率和简化代码结构。我们将从基础概念出发,逐步介绍线程池的配置、使用场景以及最佳实践,帮助开发者更好地掌握并发编程的核心技巧。
下一篇
无影云桌面