Java中的多线程

本文详细介绍了Java中的多线程概念,包括线程的创建方法(继承Thread和实现Runnable接口),线程状态及其转换,守护线程、中断机制、优先级调整以及线程安全的同步锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多线程

1.多线程概要

Thread : 多任务执行,多路径执行

线程是程序中的执行顺序流。 Java 虚拟机允许应用程序同时运行多个执行线程。

三高网站 : 高可用 高性能 高并发

线程与进程之间的区别 : 看文档

多线程的优点 : 资源利用率更好,性能更高,效率更高
多线程的缺点 : 设计复杂,可能造成数据不安全

线程的创建方式 :
1.继承Thread,重写run方法 + start开启线程

​ 2.实现Runnable接口,重写run方法 + start开启线程

​ 优点 :

	 1.类单继承,接口可以多实现

	 2.实现资源共享

​ 3.实现juc包下Callable接口,重写call方法 + 线程池

​ 优点 :

 	1.可以抛出异常

 	2.可以带出返回值

2.实现步骤

1.继承Thread

重写run方法 + start开启线程

public class Class001_Thread extends Thread{
    /*
        定义线程体
     */
    @Override
    public void run() {
        for(int i = 0;i<=100;i++){
            System.out.println("一边喝水.....");
        }
    }

    public static void main(String[] args) {
        //主线程
        // 创建线程对象
        Class001_Thread th = new Class001_Thread();
        //开启线程(准备好了)
        th.start();
        for(int i = 0;i<=100;i++){
            System.out.println("一边讲课.....");
        }
    }
}
2.实现Runnable接口

重写run方法 + start开启线程

public class Class002_Thread implements Runnable{
    /*
        定义线程体
     */
    @Override
    public void run() {
        for(int i = 0;i<=100;i++){
            System.out.println("一边喝水.....");
        }
    }

    public static void main(String[] args) {
        //主线程
        //线程所在类型对象
        Class002_Thread cs = new Class002_Thread();
        // 创建线程对象
        Thread th = new Thread(cs);
        //开启线程(准备好了)
        th.start();
        for(int i = 0;i<=100;i++){
            System.out.println("一边讲课.....");
        }
    }
}

3.内部类定义线程体
//静态内部类
    static class Inner1 implements Runnable{

        @Override
        public void run() {
            for(int i=1;i<=20;i++){
                System.out.println("一边打游戏");
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static void main(String[] args) {
        //局部内部类
        class Inner2 implements Runnable{

            @Override
            public void run() {
                for(int i=1;i<=20;i++){
                    System.out.println("一边陪女朋友");
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }

        new Thread(new Inner1()).start();
        new Thread(new Inner2()).start();

        //匿名内部类
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=1;i<=20;i++){
                    System.out.println("一边骂人..");
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }).start();

        //lambda表达式
        new Thread(()->{
            for(int i=1;i<=20;i++){
                System.out.println("一边吸烟..");
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }

3.线程状的五种态

1.新生状态 : new
2.就绪状态 : start

进入就绪状态的线程会进入到就绪队列,等待cpu的调度

如何让线程进入到就绪状态 :
1.start

2.yield礼让线程

​ yield : 礼让线程

在多线程编程中,当一个线程调用yield函数时,它暂时放弃了对CPU的控制权,让其他线程有机会运行。具体来说,yield会把当前线程状态设置为可运行状态,并将CPU资源分配给其他线程。

当其他线程运行完或者被系统中断后,原先调用yield函数的线程可以再次获得CPU的控制权,并继续执行。这是因为yield只是暂时放弃了控制权,并没有完全释放线程资源。

需要注意的是,yield并不能保证线程调度的顺序,具体哪个线程会获得CPU资源是由操作系统的调度器决定的。所以,尽管一个线程可能调用了yield,但并不能保证它会立即获得CPU的控制权。

​ 当一个线程调用yield,会从运行恢复到就绪状态,同时让出cpu的资源

​ static void yield() 向调度程序提示当前线程愿意放弃其当前对处理器的使用。

​ 3.cpu的调度切换

​ 4.阻塞解除

3.运行状态 :cpu调度执行
4.阻塞状态 : 无法正常运行

如何让线程进入到阻塞状态 :

1.sleep

​ sleep : 线程休眠

	static void sleep(long millis)  使当前执行的线程休眠(暂时停止执行)指定的毫秒数,取决于系统计时器和调度程序的精度和准确性。

​ 线程会进入阻塞状态,同时让出cpu的资源

​ 抱着资源睡觉,抱着对象的锁资源睡觉

​ 作用 :
1.模拟网络延迟

​ 2.放大问题出现的可能性

2.join

​ join : 插队线程 | 合并线程

​ final void join() 等待这个线程死掉。

​ final void join(long millis) 最多等待millis毫秒让该线程终止。

​ final void join(long millis, int nanos) 最多等待millis毫秒加上nanos纳秒,以使该线程终止。

​ 注意 : 先就绪后插队

​ 3.wait

​ 4.IO

5.终止状态

如何让线程进入终止状态 :

​ 1.正常执行到终止

​ 2.stop…不推荐

​ 3.通过添加标识判断方式–>推荐

注意 :

​ 一旦一个线程进入到终止状态无法恢复

​ 一个线程当阻塞状态解除会直接恢复到就绪状态

6.getState

getState :获取 当前线程的 状态

​ 线程状态。 线程可以处于以下状态之一:

  NEW -> 新生		尚未启动的线程处于此状态。

​ RUNNABLE --> 就绪 |运行 在 Java 虚拟机中执行的线程处于这种状态。

​ BLOCKED ->阻塞等待获取对象锁 阻塞等待监视器锁的线程处于此状态。

​ WAITING ->等待其他线程执行特点操作 join() wait()… 无限期等待另一个线程执行特定操作的线程处于此状态。

 TIMED_WAITING ->与时间相关的阻塞  sleep(ms) join(ms) wait(ms) ...		等待另一个线程执行操作达指定等待时间的线程处于此状态。

  TERMINATED ->终止状态		已退出的线程处于此状态。

4.守护线程 :

​ 当所有的用户线程全部执行完毕,守护线程无论是否执行完毕,JVM都会直接退出

​ 守护线程是用来守护用户线程的

​ 当创建一个线程默认为用户线程,如果想要 设置成为守护线程 final void setDaemon(boolean on) 将此线程标记为daemon线程或用户线程。 true->守护 false->用户

​ 注意 : 垃圾回收机制是典型守护线程

​ 先设置守护后设置就绪

5.中断线程 :

​ void interrupt() 中断这个线程。为当前调用interrupt方法的线程设置中断标识

​ static boolean interrupted() 测试当前线程是否被中断。 判断当前正在执行的线程是否曾经调用interrupt方法添加过中断标识,同时复位标识

​ boolean isInterrupted() 测试此线程是否已被中断。判断调用isInterrupted方法的线程是否曾经调用interrupt方法添加过中断标识

注意 : InterruptedException - 如果有任何线程中断了当前线程。 抛出此异常时清除当前线程的中断状态。

6.线程优先级 :

​ 当大一个线程优先执行可能性

​ 1~10 1最小 10最大 5默认

​ final int getPriority() 返回此线程的优先级。

​ final void setPriority(int newPriority) 更改此线程的优先级。

​ static final int MAX_PRIORITY 线程可以拥有的最大优先级。

​ static final int MIN_PRIORITY 线程可以拥有的最低优先级。

​ static final int NORM_PRIORITY 分配给线程的默认优先级。

注意 :如果在 一个线程已经结束之后修改优先级,这个修改没有效果

*7.线程安全 :

​ 多个线程同时操作同一份资源,才有可能遇到线程数据不安全问题–>需要控制安全

同步锁 :

​ 原理 : 让多个线程执行某段有可能影响数据安全的一段代码的时候,排队执行

​ 实现关注两个部分 :

​ 1.控制|协调多个线程排队执行的条件

​ 锁定一个对象,利用对象锁机制控制

​ this : 索引使用的是当前调用成员方法的对象

​ 类的Class对象 : 每一个类只有一个,不会改变,在类加载到内存之后已经存在

​ 获取一个类的Class对象 : 类名.class

​ 资源(对象)

​ 2.多个线程排队执行的代码范围

​ 使用语法 :

​ 同步方法 : 使用synchronized关键字修饰方法

​ 排队执行的代码范围 : 整个方法体

​ 协调多个线程排队执行的条件 :

​ 成员方法 : this

​ 静态方法 : 类的Class对象

​ 同步块 :多个线程排队执行同步块{}中的代码

​ synchronized(条件){

​ 排队执行代码段;

​ }

当锁类的时候,相当于锁了这个类的所有对象,无论创建了这个类的多少个对象,这个类的Class对象只有一个,如果只想要锁这个类的某一个对象,建议使用this|具体对象

当锁this的时候,相当于锁了这个对象的所有资源(成员),当指向锁具体 的某一个资源的时候,可以锁资源

注意 :

​ 锁不变的东西,自定义引用数据类型的对象地址一定不变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值