IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 2021-10-29线程池多线程(面试) -> 正文阅读

[Java知识库]2021-10-29线程池多线程(面试)

1.什么是线程?线程和进程的区别?

线程:是进程的一个实体,是cpu调度和分派的基本单位,是比进程更小的可以独立运行的基本单位。

进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行资源分配和调度的一个独立单位。

特点:线程的划分尺度小于进程,这使多线程程序拥有高并发性,进程在运行时各自内存单元是相互独立的,线程之间内存共享,这使得多线程编程可以拥有更好的性能和用户体验。

2.创建线程的几种方式?

1.继承Thread类并重写run方法创建线程,实现简单但不可以继承其他类

2.实现Runnable接口并重写run方法。避免了单继承的局限性,编程灵活,实现解耦。

3.实现Callable接口并重写了call方法,创建线程。可以获取线程执行结果的返回值,并且可以抛出异常。

4.使用线程池创建

package cn.tedu.day01;
 
import java.util.Random;
import java.util.concurrent.Callable;
/*创建一个类,实现Callable接口(泛型类型自定义)
重写Callable接口中的call方法
创建Callable接口的实现类对象
创建FutureTask创建,把Callable实现类对象传入到FutureTask构造方法中
创建Thread对象,把FutureTask对象传入到Thread类的构造方法中
开启线程
通过FutureTask对象调用get方法,拿到返回值,线程才结束。
* */
public class ThreadDemo3 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        return new Random().nextInt(10);
    }
}
 
package cn.tedu.day01;
 
import java.util.concurrent.FutureTask;
 
public class ThreadTest3 {
    public static void main(String[] args) throws Exception{
        ThreadDemo3 threadDemo3 = new ThreadDemo3();
        FutureTask<Integer> futureTask = new FutureTask<>(threadDemo3);
        Thread thread = new Thread(futureTask);
        thread.start();
        //拿到线程返回值时,线程才结束
        Integer integer = futureTask.get();
        System.out.println(integer);
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}

3.Runnable和Callable的区别?

Runnable接口run方法无返回值;Callable接口call方法有返回值,支持泛型

Runnable接口run方法只能抛出运行时异常,且无法捕获处理;Callable接口call方法允许抛出异常,可以获取异常信息

4.如何启动一个新线程,调用start和run方法的区别?

线程对象调用run方法不开启线程,仅是对象调用方法。

线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行。

5.线程有哪几种状态以及各种状态之间的转换?

1.新建状态。生产线程对象,但是并没有调用该对象的start方法

2.就绪状态。当调用了线程对象的start方法之后,此时线程调度程序还没有把该线程设置成当前线程,处于就绪状态

3.运行状态。线程调度程序将处于就绪状态的线程设置成当前线程,此时线程进入了运行状态,可以执行run函数中的代码

4.阻塞状态。阻塞状态是线程因为某种原因放弃了cpu使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞情况分三种:

(1)等待。通过调用线程的wait()方法,让线程等待某工作的完成

(2)超时等待。通过调用线程的sleep()或join()或者发出了I/O请求时,线程会进入到阻塞状态。当sleep状态超时,join()等待线程终止或者超时、或者I/O处理完毕了,线程重新进入就绪状态。

(3)同步阻塞-线程在获取synchronized同步锁失败(因为锁被其它线程占用),它会进入同步阻塞状态。

5.死亡状态。线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

6.线程相关的基本方法?

线程相关的基本方法有 wait,notify,notifyAll,sleep,join,yield 等

7.wait()与sleep()的区别?

  • 来自不同的类
  • 关于锁的释放
  • 使用的范围
  • 是否需要捕获异常

线程池

1.为什么需要线程池?

在实际使用中,线程是很占用系统资源的,如果对线程管理不完善的话就很容易导致系统问题。因此,在大多数并发框架中都会使用线程池来管理线程。

1.线程池可以重复利用已有的线程继续执行任务,避免线程在创建消耗时造成的消耗

2.由于没有线程创建和消耗时的消耗,可以提高系统响应速度

3.通过线程池可以对线程进行合理的管理,根据系统的承受能力可以随时调整可运行线程数量的大小。

2.线程池的分类

1.newCachedThreadPool:创建一个可进行缓存重复利用的线程池

2.newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列来运行这些线程,线程池中的线程处于一定的量,可以很好的控制线程的并发量

3.newSingleThreadExecutor:线程池最多执行一个线程,之后提交的线程将会排在队列中以此执行。

4.newSingleThreadScheduledExecutor:创建一个单线程执行程序,它可 安排在给定延迟后运行命令或者定期执行

5.newScheduledThreadPool:创建一个线程池,他可安排在给定延迟后运行命令或者定期执行。

6.newWordStealingPool:创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多个线程在执行,如果不传并行级别参数,将默认为当前系统的CPU个数。

3.核心参数:

corePoolSize 核心线程池的大小

maximumPoolSize 线程池能创建线程的最大个数

keepAliveTime 空闲线程存活时间

unit:时间单位,为keepAliveTime指定时间单位

workQueue:阻塞队列,用于保存任务的阻塞队列

ThreadFactory:创建线程的工程类

handler:饱和策略(拒绝策略)

4.线程池的原理

  1. 一个任务,已存在的一个核心线程,可以解决
  2. 多个任务,等待的任务!!没有超过阻塞队列长度,存放在阻塞队列中,等待核心线程依次执行!
  3. 多个任务,等待的任务超过了阻塞队列的最大长度,就会开始创建新的线程,如果新建线程数+核心线程数>最大线程数,直接报错;如果没有超过,那就正常创建,核心线程增加,分摊任务!!

5.拒绝策略(保护策略)

ThreadPoolExecutor.AbortPolicy(系统默认): 丢弃任务并抛出 RejectedExecutionException 异常,让你感知到任务被拒绝了,我们可以根据业务逻辑选 择重试或者放弃提交等策略

  1. ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常,相对而 言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失
  2. ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常,相对而 言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失风险
  3. ThreadPoolExecutor.CallerRunsPolicy:既不抛弃任务也不抛出异常,而是将某些任务 回退到调用者,让调用者去执行它。

6.线程池的关闭。

原理都是:遍历线程池中的所有线程,然后依次中断。

shutdownNow 首先将线程池的状态设置为 STOP,然后尝试停止所有的正在执行和未执行任务的线程,并返回等待执行任务的列表

shutdown 只是将线程池的状态设置为 SHUTDOWN 状态,然后中断所有没有正在执行任务的线程

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章           查看所有文章
加:2021-11-05 17:17:55  更:2021-11-05 17:18:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:44:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码