当前位置: 首页 > news >正文

什么是多线程?线程池?

文章目录

  • 一、什么是多线程?
  • 二、多线程的实现方法
    • 1. 继承Thread类,重写run方法
    • 2. 实现Runnable接口,并创建Thread对象
    • 3. Callable和Future
  • 三、线程的5种状态
      • **New(新创建)**
      • **Runnalbe(可运行)**
      • **Running**
      • **Blocked(阻塞)**
      • **等待(Waiting)**
      • **锁定(Lock)**
      • **死亡(Dead)**
  • 四、线程池的三大方法、七大参数、四种拒绝策略
      • 线程池的三大方法:
      • 线程池的七大参数:
      • 线程的四大拒绝策略:
  • 五、线程池的五种状态
      • RUNNING
      • SHUTDOWN
      • STOP
      • TIDYING
      • TERMINATED


一、什么是多线程?

在 Java 中,多线程是指在一个进程中同时执行多个线程,每个线程都可以独立地执行特定的任务。线程是轻量级的进程,它们共享同一个进程的资源,包括内存空间、文件句柄等。通过多线程,可以提高程序的并发性和性能,因为多个线程可以同时执行,从而更好地利用 CPU 资源。
简单来说: 就是老板请员工帮你去做事。

二、多线程的实现方法

1. 继承Thread类,重写run方法

class ExtendThread extends Thread {      // 继承自Thread
    private String name;
 
    public ExtendThread(String name) {
        this.name = name;
    }
 
    @Override
    public void run() {                      // 必须重写run方法,并且将线程任务放到run里执行
        for (int i = 0; i < 5; i++) {
            System.out.println(name + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
 
public class Example {
    public static void main(String[] args) {
        ExtendThread t1 = new ExtendThread("线程A");
        ExtendThread t2 = new ExtendThread("线程B");
        t1.start();
        t2.start();
    }
}

2. 实现Runnable接口,并创建Thread对象

class MyRunnable implements Runnable {   // 必须要实现Runnable接口
 
    private String name;
 
    public MyRunnable(String name) {
        this.name = name;
    }
 
    public void run() {                // 必须要有run方法,并且将需要执行的任务放到run方法里
        for (int i = 0; i < 5; i++) {
            System.out.println(name + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
 
public class Example {
    public static void main(String[] args) {
        MyRunnable run1 = new MyRunnable("线程A");
        MyRunnable run2 = new MyRunnable("线程B");
 
        Thread t1 = new Thread(run1);
        Thread t2 = new Thread(run2);
        t1.start();
        t2.start();
    }
}

3. Callable和Future

前面创建线程的2种方式,都有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。
Callable和Future,它俩 一个产生结果,一个拿到结果Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,因而Callable功能更强些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值。

 
public interface Callable<V> {
 
    V call() throws Exception;
}

三、线程的5种状态

在这里插入图片描述

New(新创建)

当用new创建一个新线程时,如new Thread®,该线程还没有开始运行,此时的状态为新创建状态。此时,程序还没有开始运行线程中的代码,在线程运行之前还有一些基本工作要做。

Runnalbe(可运行)

一旦调用start方法,线程便进入了可运行状态。一个可运行的线程可能正在运行,也可能没有运行,这取决于系统在该时间片里是否调度了该线程。对于常用的抢占式调度系统,它会给每一个可运行线程一个时间片来执行任务,当时间片用完时,操作系统便剥夺该线程的运行权,并给另一个线程运行机会。当选择下一个线程时,操作系统会考虑线程的优先级。不过也有一些操作系统,如像手机,采用的可能是协作式调度系统,在这样的系统中,一个线程只有在调用yield方法、或者被阻塞、或者被等待时,线程才失去控制权。

Running

就是运行状态

Blocked(阻塞)

对于阻塞状态,又可以根据阻塞原因的不同,将其细分为三种类型,分别是等待(Waiting)、锁定(Lock)和其他。处于阻塞状态的线程共同点都是暂时不活动,直到调度器重新激活它。

等待(Waiting)

正在运行的线程内部调用wait()时,该线程便进入阻塞状态(wait()是Object类的方法),并且在wait所在的代码行处停止执行,直到接到通知(notify)或被中断(等待时间到)为止。

需要注意的是:在调用wait方法之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait方法。

锁定(Lock)

当一个线程视图获取一个内部的对象锁,而该锁却被其他线程持有时,此时这个线程就进入阻塞状态,当所有其他线程释放该锁,并且线程调度器允许该线程持有它的时候,该线程才会变为Runnalbe状态。

其他
另外,还有如果在线程内部调用了sleep()或者jion()方法时,也会使该线程进入阻塞状态。sleep()是指让这个线程休息一段时间,时间到了之后再进入Runnalbe,jion()一般用在主线程中,表示主线程等待子线程把活干完了,再接着往下执行。

死亡(Dead)

线程进入死亡状态主要有以下两种原因:第一,run方法运行完毕,正常退出;第二,因为一个没有捕获的异常终止了run方法,导致线程意外死亡。

四、线程池的三大方法、七大参数、四种拒绝策略

线程池的三大方法:

ExecutorService service = Executors
.newSingleThreadExecutor();//单个线程
.newFixedThreadPool(5);//创建一个固定的线程池的大小
.newCachedThreadPool();//缓存线程池,可伸缩的

线程池的七大参数:

public ThreadPoolExecutor
(
int corePoolSize,//核心线程数
int maximumPoolSize,//最大的线程数
long keepAliveTime,//存活时间
TimeUnit unit,//存活时间的时间单位
BlockingQueue workQueue//阻塞队列)
ThreadFactory threadFactory,//线程工厂,创建线程的,一般不动
RejectedExecutionHandler handler//拒绝策略

)

线程的四大拒绝策略:

第一种拒绝策略:new ThreadPoolExecutor.AbortPolicy(),如果线程满了,则不处理新的进程,抛出异常;
第二种处理策略:new ThreadPoolExecutor.CallerRunsPolicy(),线程池满了,如果有新的哪里来的去哪里,不会抛出异常
第三种处理策略:new ThreadPoolExecutor.DiscardPolicy(),线程池满了,丢掉线程,不会抛出异常
第四种处理策略:
阿里巴巴开发手册对于线程池使用的规范: oom-> out of memory 内存耗尽
在这里插入图片描述

五、线程池的五种状态

线程池的五种状态:
Running、Shutdown、Stop、Tidying、Terminated
分别为:

RUNNING

RUNNING;
● 线程池处于RUNNING状态时,线程池能够接收新任务,也能够对已经添加的任务进行处理;
● 线程池一被创建,线程池的状态就是RUNNING状态;

SHUTDOWN

SHUTDOWN;
● 线程池已经被关闭了,不再接收新任务;但是,其还是会处理队列中的剩余的任务;
● 调用线程池的shutdown()方法后,线程池的状态就会由RUNNING转为SHUTDOWN;

STOP

STOP;
● 线程池处于STOP状态,此时线程池不再接收新任务,不处理已经添加进来的任务,并且会中断正在处理的任务;
● 调用线程池的shutdownNow()方法后,线程池的状态就会由RUNNING或SHUTDOWN转为STOP;

TIDYING

TIDYING;
● 线程池被下达关闭命令后,如果当前所有的任务都已经终止了(这个终止可以表示执行结束,也可以表示强制中断,也可以表示被丢弃) ,那么线程就会进入TIDYING状态;当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
● 如果线程状态已经是SHUTDOWN了,并且线程中以及队列中都没有任务时,线程池就会由SHUTDOWN转为TIDYING;如果线程池状态为STOP,那么当线程池把所有的任务都给清理干净时,线程池就会由STOP转为TIDYING;

TERMINATED

TERMINATED;
● 线程池就结束了;线程池就不能重新启动了;
● 如果线程池处于TIDYING状态,那么当线程池执行完terminated()方法后,线程池状态就会由TIDYING转为TERMINTED;

相关文章:

  • 基于vue3和spring boot实现大文件上传
  • 2025年2月21日优雅草内测分发站全新升级-测试运营-优雅草内测分发站新用户提供免费100下载点-2月28日正式运营并且提供私有化部署版本
  • GPT大语言模型与搜索引擎:技术本质与应用场景的深度解析
  • 第十四届蓝桥杯大赛软件赛国赛C/C++大学C组
  • Nodejs-逐行读取文件【简易版】
  • 金融赋能绍兴纺织 民生银行助力外贸中小微企业“走出去”
  • 算法题(81):询问学号
  • 服务器禁止操作汇总(Server Prohibits 0peration Summary)
  • 会话与会话管理:Cookie与Session的深度解析
  • shell中 <<<(Here String)的使用
  • etcd部署硬件资源推荐
  • 搭建数字化生态平台公司:痛点与蚓链解决方案
  • Zookeeper(79)如何进行Zookeeper的监控?
  • 回溯算法中的for循环和递归使用
  • 自动化测试框架设计
  • Unity 优化封装常用API和编辑器扩展工具包
  • Redis的过期策略及其优缺点
  • FPGA之硬件设计笔记-持续更新中
  • python-leetcode-颜色分类
  • 安全模块设计:token服务、校验注解(开启token校验、开启签名校验、允许处理API日志)、获取当前用户信息的辅助类
  • 闵行西安网站建设/东莞seo外包公司
  • 网站更多分享怎么做/百度游戏风云榜
  • 陕西网站建设方案/深圳网站seo推广
  • 北京住房和城乡建设委员会网站6/百度经验官网登录
  • 企业网站的网页设计/seo快速排名软件首页
  • php外贸网站/sem优化是什么意思