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


目录
相关文章
|
22小时前
|
安全 Java 容器
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第18天】随着多核处理器的普及,并发编程变得越来越重要。Java提供了丰富的并发编程工具,如synchronized关键字、显式锁Lock、原子类、并发容器等。本文将深入探讨Java并发编程的核心概念,包括线程安全、死锁、资源竞争等,并分享一些性能优化的技巧。
|
1天前
|
安全 Java
Java一分钟之-并发编程:原子类(AtomicInteger, AtomicReference)
【5月更文挑战第18天】Java并发编程中的原子类如`AtomicInteger`和`AtomicReference`提供无锁原子操作,适用于高性能并发场景。`AtomicInteger`支持原子整数操作,而`AtomicReference`允许原子更新对象引用。常见问题包括误解原子性、过度依赖原子类以及忽略对象内部状态的并发控制。要避免这些问题,需明确原子操作边界,合理选择同步策略,并精确控制原子更新。示例代码展示了如何使用这两个类。正确理解和使用原子类是构建高效并发程序的关键。
9 1
|
1天前
|
安全 Java 容器
Java一分钟之-并发编程:并发容器(ConcurrentHashMap, CopyOnWriteArrayList)
【5月更文挑战第18天】本文探讨了Java并发编程中的`ConcurrentHashMap`和`CopyOnWriteArrayList`,两者为多线程数据共享提供高效、线程安全的解决方案。`ConcurrentHashMap`采用分段锁策略,而`CopyOnWriteArrayList`适合读多写少的场景。注意,`ConcurrentHashMap`的`forEach`需避免手动同步,且并发修改时可能导致`ConcurrentModificationException`。`CopyOnWriteArrayList`在写操作时会复制数组。理解和正确使用这些特性是优化并发性能的关键。
6 1
|
1天前
|
Java 编译器
Java并发编程中的锁优化策略
【5月更文挑战第18天】在Java并发编程中,锁是一种常用的同步机制,用于保护共享资源的访问。然而,不当的锁使用可能导致性能问题和死锁风险。本文将探讨Java中锁的优化策略,包括锁粗化、锁消除、锁分离和读写锁等技术,以提高并发程序的性能和可靠性。
|
1天前
|
自然语言处理 Java API
Java 8的Stream API和Optional类:概念与实战应用
【5月更文挑战第17天】Java 8引入了许多重要的新特性,其中Stream API和Optional类是最引人注目的两个。这些特性不仅简化了集合操作,还提供了更好的方式来处理可能为空的情况,从而提高了代码的健壮性和可读性。
24 7
|
1天前
|
Java 编译器
Java 并发编程中的锁优化策略
【5月更文挑战第17天】在 Java 并发编程中,锁是一种常见的同步机制,用于保护共享资源的访问。然而,不当使用锁可能导致性能问题和死锁风险。本文将探讨 Java 中的锁优化策略,包括锁粗化、锁消除、锁降级以及读写锁等技术,以提高并发程序的性能和可靠性。
|
2天前
|
Java 编译器
Java并发编程中的锁优化策略
【5月更文挑战第17天】在Java并发编程中,锁是一种常见的同步机制,用于保护共享资源。然而,使用不当的锁可能导致性能下降和死锁等问题。本文将探讨Java中锁的优化策略,包括锁粗化、锁消除、锁排序等方法,以提高程序的性能和可靠性。
|
2天前
|
存储 关系型数据库 MySQL
《MySQL 入门教程》第 05 篇 账户和权限,Java高并发编程详解深入理解pdf
《MySQL 入门教程》第 05 篇 账户和权限,Java高并发编程详解深入理解pdf
|
2天前
|
设计模式 算法 Java
Java的前景如何,好不好自学?,万字Java技术类校招面试题汇总
Java的前景如何,好不好自学?,万字Java技术类校招面试题汇总
|
2天前
|
NoSQL Dubbo Java
StringBoot编程式事务与声明式事务java工程师面试突击第一季
StringBoot编程式事务与声明式事务java工程师面试突击第一季