Java中线程详解


相关概念

并行:在同一时刻,有多个任务在多个CPU上同时执行
并发:在同一时刻,有多个任务在一个CPU上交替执行
进程:正在执行的程序
线程:应用程序中做的事情,是程序运行的基本执行单元
当操作系统执行一个程序时,会在系统中建立一个进程,该进程必须至少建立一个线程(这个线程被称为主线程),作为这个程序运行的入口点。因此,在操作系统中运行的任意程序都至少有一个线程。

多线程

概念

是指从软件或者硬件上实现多个线程并发执行的技术

实现方式

继承Thread类

Snipaste_2024-04-02_20-47-06.png

  1. 创建一个类继承Thread类
  2. 在类中重写run方法(线程执行的任务在该方法中)
  3. 创建线程对象,调用线程的start方法开启线程
实现Runnable接口

Snipaste_2024-04-02_20-47-44.png

  1. 定义一个类实现Runnable接口,并重写run方法(可以用匿名内部类实现)
  2. 创建任务对象
  3. 使用还有Runnable参数的构造方法创建线程对象并指定对象
  4. 调用线程的start方法,开启线程
利用Callable接口,FutureTask类来实现

Snipaste_2024-04-04_10-54-57.png
Snipaste_2024-04-04_10-55-25.png

比较
  1. 只能单继承,线程任务和线程功能都在Thread子类中
  2. 能多实现,线程任务在Runnable接口实现类中或FutureTask对象中,线程功能在Thread类中;有解耦的好处

Snipaste_2024-04-04_10-57-38.png
接口一是用来制定规则,二是用来降低耦合(紧密连接的程度)

常用方法

Snipaste_2024-04-04_10-43-39.png

线程安全

产生的原因

多个线程对于同一个数据,进行读写操作,造成数据错乱

解决思想

把多个线程操作的共享数据,存放到一个安全的环境中
Java语言基于线程安全的问题,提供了同步机制

同步

同步代码块

Snipaste_2024-04-02_22-01-13.png

同步方法

Snipaste_2024-04-02_22-01-50.png

Lock锁机制

Snipaste_2024-04-02_22-03-13.png

死锁

概念

同步代码块的锁进行嵌套使用,就会大概率产生死锁

避免

不使用锁的嵌套

状态

Snipaste_2024-04-03_20-10-18.png
Snipaste_2024-04-03_20-10-41.png

线程间的通讯

介绍

通过等待和唤醒机制,来实现多个线程协调操作完成某一项任务
等待唤醒机制其实就是让线程进入等待状态或者让线程从等待状态中唤醒

方法

  • 等待方法
    • 特殊之处:会释放掉对象锁
wait() //无限等待,(只能其他线程唤醒)
wait(Long 毫秒) //计时等待(时间到了自动唤醒)
  • 唤醒方法
    • 特殊之处:不会释放掉对象锁
notify() //唤醒处于"等待状态"的任意一个线程
notifyAll() // 唤醒处于"等待状态"的所以线程

注意

  1. 等待和唤醒的方法,都要使用锁对象调用(需要在同步代码块中使用)
  2. 等待和唤醒方法应该使用相同的锁对象调用

生产者消费者案例

public class Resource {
    //共享资源
    static int num = 0;

    static final Object LOCK = new Object();
}
public class ConsumerTask implements Runnable {

    @Override
    public void run() {
        while (true) {
            synchronized (Resource.LOCK) {
                if (Resource.num == 0) {
                    //进入等待状态
                    System.out.println(Thread.currentThread().getName() + "发现没有食物,进入等待状态。。。");
                    try {
                        Resource.LOCK.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    //有食物,吃完并唤醒
                    System.out.println(Thread.currentThread().getName() + "发现有食物,吃完并唤醒");
                    Resource.num--;
                    Resource.LOCK.notify();
                }
            }
        }
    }
}
public class ProducerTask implements Runnable {

    @Override
    public void run() {
        while (true) {
            synchronized (Resource.LOCK) {
                if (Resource.num == 0) {
                    //生产食物并唤醒消费者
                    System.out.println(Thread.currentThread().getName() + "生产了食物,唤醒消费者");
                    Resource.num = 1;
                    Resource.LOCK.notify();
                } else {
                    //有食物,等待
                    System.out.println(Thread.currentThread().getName() + "发现有食物,进入等待状态");
                    try {
                        Resource.LOCK.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
            }
        }
    }
}
public class Test {
    public static void main(String[] args) {
        new Thread(new ConsumerTask(),"消费者").start();
        new Thread(new ProducerTask(),"生产者").start();
    }
}

线程池

介绍

是一个可以复用线程的技术
原因:用户每次发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理,而创建新线程的开销是很大,并且请求过多时,肯定会有大量的线程被创建出来,这会影响性能,就需要线程池了

创建

ExecutorService接口
Snipaste_2024-04-04_11-30-32.png
方式一
Snipaste_2024-04-04_11-31-02.png
方式二
Snipaste_2024-04-04_11-42-36.png
Snipaste_2024-04-04_11-44-13.png
注意事项

  1. 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程
  2. 核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务

常用方法

Snipaste_2024-04-04_11-47-25.png
Snipaste_2024-04-04_11-45-57.png

处理

  1. 处理Runnable任务
  2. 处理Callable任务
  • 37
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@Zeal

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值