首页>>后端>>java->Java并发之线程与线程池

Java并发之线程与线程池

时间:2023-12-05 本站 点击:0

我们经常听到一些大佬说一些概念,比如线程不安全,那到底什么是线程不安全呢?

 线程不安全指的是,我们在多线程的环境下,操作一些共享数据的时候可能会让我们无法得到期望的结果

线程

为什么会出现线程呢?

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!

我们先来看一下线程6种状态的状态

线程状态

New(新生态)

Runnable(可运行态)

在可运行态中又可以分为,Running(运行态)和Ready(就绪态)

Running(运行态)

运行态指的是,该线程已经获取了CPU的时间片,简单来说,就是该线程正在运行

Ready(就绪态)

而就绪态指的是,该线程万事俱备只欠“东风”,就差CPU给他分配时间片了

Blocking(阻塞态) 线程在获取锁失败之后,就会进入该状态,当该线程获取了锁就会结束该状态,所有阻塞状态的线程都会放在阻塞队列中。

Waiting(等待态)

当处于运行态的线程调用wait(),park(),join()方法后,就会进入该状态,处于等待态的线程,会释放CPU时间片,并且会释放资源(例如锁),这个状态下的线程只能等待其他线程来唤醒它。

Timed Waiting(超时等待态)

超时等待态和等待态类似,不过这个状态的线程不需要显式地去唤醒,这个状态的线程在超过一定时间后,将由系统自动唤醒

Terminated(结束态) 线程结束后的状态

线程的三种使用方式

线程的使用方式有三种,分别是实现Runnable接口、实现Callable接口、继承Thread类

实现Runnable接口

 创建一个自定义类然后实现该接口,实现该接口的run()方法 然后在我们需要使用该类的地方直接去实例化即可

实现Callable接口

创建一个自定义类然后实现该接口,实现该接口的call()方法然后通过开启线程池服务来创建该类

继承Thread类

创建一个自定义类然后继承该类,需要重写该类的run()方法这种方式其实和实现Runnable接口的方式类似,因为Thread类也实现了Runnable接口我们在实现的时候直接去实现即可

三种方式的对比

其实我们更加推荐实现Runable接口的这种方式,因为相较于其他两种,实现Callable接口这种方式使用起来更加繁琐,而继承Thread类的这种方式是继承,我们都知道在Java中是不支持多重继承的,但是支持多重实现,并且用起来实现Runnable接口这种方式也更加简单

线程之间的协作工作

join()方法

我们在很多情况下,会在一个线程中调用另一个线程的方法,这个时候我们就会使用到join方法了

在这里我们先定义一个线程类,为了方便我们直接去继承Thread类

public class YlOneThread extends Thread {    @Override    public void run() {        System.out.println("我是亚雷1线程");            }}

在这里我们又定义了一个线程类,不过在这个线程类中需要使用前面那个线程

public class YlTwoThread extends Thread{    private YlOneThread thread;    public YlTwoThread(YlOneThread thread){        this.thread = thread;    }    @Override    public void run() {        try {            thread.join();        } catch (InterruptedException e) {                       e.printStackTrace();        }        System.out.println("我是亚雷2线程");            }    }

最后我们再创建一个测试类来测试

public class test {    public static void main(String[] args) {        YlOneThread Thread1 = new YlOneThread();        YlTwoThread Thread2 = new YlTwoThread(Thread1);        Thread2.start();        Thread1.start();    }}

我们可以很明显的看到再线程2中调用了线程1不出意外我们得到了这样的结果

我是亚雷1线程我是亚雷2线程

在这里虽然是线程2先启动,不过在线程2中调用了线程1,线程2会先等待线程1完成然后继续执行

wait()、notify()、notifyAll()方法.

在这里我就简略的说一下这些方法、因为这些方法并不是来自于JUC包下的而是来自于Object类下面的

wait()方法

这个方法在前面我们也见过了,让线程进入等待态并且也会释放资源(锁)

notify()、notifyAll()方法

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!0

wait()和sleep()

我们经常拿这两个方法进行比较、因为它们在我们浅层的认识中都是使线程进行等待

其实它们大相径庭

wait()方法会释放资源(锁),这在前面我们已经知道了, 而sleep()方法并不会释放资源(锁)

wait()方法是基于Object的方法,而sleep()是基于Thread类的方法

await()、signal()、signalAll()方法

而在JUC中我们使用这些方法来实现线程间的调度

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!1

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!2

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!3

这种方法很明显wait()那一套更加灵活

线程池

说到线程池,我们不得不提一下线程池的七大参数了。

线程池七大参数

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!4

corePoolSize 核心线程数

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!5

maximumPoolSize 最大线程数

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!6

keepAliceTime 线程空闲的存活时间

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!7

unit 线程存活时间单位

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!8

workQueue 工作队列

 线程就好比一个人,俗话说的好,众人拾柴火焰高,而多线程也是这个道理!9

threadFactory 线程工厂

 创建一个自定义类然后实现该接口,实现该接口的run()方法 然后在我们需要使用该类的地方直接去实例化即可0

handler 饱和策略

 创建一个自定义类然后实现该接口,实现该接口的run()方法 然后在我们需要使用该类的地方直接去实例化即可1

线程池的执行流程

线程池到底是怎么来创建线程的呢?

 创建一个自定义类然后实现该接口,实现该接口的run()方法 然后在我们需要使用该类的地方直接去实例化即可2

原文:https://juejin.cn/post/7097417085164191751


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/12193.html