JavaSE-线程池(1)- 线程池概念

news2024/9/28 21:22:15

JavaSE-线程池(1)- 线程池概念

前提

使用多线程可以并发处理任务,提高程序执行效率。但同时创建和销毁线程会消耗操作系统资源,虽然java 使用线程的方式有多种,但是在实际使用过程中并不建议使用 new Thread 的方式手动创建线程。

线程池概念

线程池可以理解成一个存放线程的容器,当需要使用线程处理任务时从线程池中取,而并非直接创建一个线程

使用线程池的优势

  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

来自 《Java 并发编程的艺术》

线程池相关接口以及类

Runnable

可以理解成一个不需要获取返回结果的任务

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Callable

类似于 Runnable ,是一个有返回结果的任务

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

Future

异步任务提交后使用 Future 接收,从 Future get 方法可以获取异步任务的返回值

public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);
    

    boolean isCancelled();

   
    boolean isDone();

    
    V get() throws InterruptedException, ExecutionException;

    
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

RunnableFuture

Runnable 和 Future 的结合体

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

FutureTask

RunnableFuture 接口的实现类

public class FutureTask<V> implements RunnableFuture<V> {
}

使用demo:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureTaskTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask = new FutureTask(() -> {
            Thread.sleep(1000);
            return 100;
        });

        new Thread(futureTask).start();
        System.out.println(futureTask.get());
    }
}

Executor

执行器,用来执行 Runnable 任务,通过实现 Executor 接口可以自定义任务的执行方式,比方使用线程池来执行任务,避免使用 new Thread 的方式来执行

public interface Executor {

    /**
     * 执行方法,执行一个具体的 Runnable 任务
     */
    void execute(Runnable command);
}

ExecutorService

继承自 Executor ,提供更多的方法,实现线程池的类一般继承这个接口

public interface ExecutorService extends Executor {

    /**
     * 关闭执行器,但是会等待已经提交的任务执行完成,不再接收新的任务
     */
    void shutdown();

    /**
     * 尝试停止所有正在执行的任务,不再接收新的任务
     */
    List<Runnable> shutdownNow();

    /**
     *判断执行器是否关闭,如果此执行器已关闭,则返回true。
     */
    boolean isShutdown();

    /**
     * 如果关闭后(调用 shutdown 或 shutdownNow 方法)所有任务都已完成,则返回true。
     * 请注意,除非首先调用shutdown或shutdownNow,否则isTerminated       永远不会为true。
     */
    boolean isTerminated();

    /**
     * Blocks until all tasks have completed execution after a shutdown
     * request, or the timeout occurs, or the current thread is
     * interrupted, whichever happens first.
     */
    boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;

    /**
     * 提交一个有返回值的任务并使用 Future 接收
     */
    <T> Future<T> submit(Callable<T> task);

    /**
     * Submits a Runnable task for execution and returns a Future
     * representing that task. The Future's {@code get} method will
     * return the given result upon successful completion.
     */
    <T> Future<T> submit(Runnable task, T result);

    /**
     * 提交任务并使用 Future 接收
     */
    Future<?> submit(Runnable task);

    /**
     * Executes the given tasks, returning a list of Futures holding
     * their status and results when all complete.
     * {@link Future#isDone} is {@code true} for each
     * element of the returned list.
     * Note that a <em>completed</em> task could have
     * terminated either normally or by throwing an exception.
     * The results of this method are undefined if the given
     * collection is modified while this operation is in progress.
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;

    /**
     * Executes the given tasks, returning a list of Futures holding
     * their status and results
     * when all complete or the timeout expires, whichever happens first.
     * {@link Future#isDone} is {@code true} for each
     * element of the returned list.
     * Upon return, tasks that have not completed are cancelled.
     * Note that a <em>completed</em> task could have
     * terminated either normally or by throwing an exception.
     * The results of this method are undefined if the given
     * collection is modified while this operation is in progress.
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;

    /**
     * Executes the given tasks, returning the result
     * of one that has completed successfully (i.e., without throwing
     * an exception), if any do. Upon normal or exceptional return,
     * tasks that have not completed are cancelled.
     * The results of this method are undefined if the given
     * collection is modified while this operation is in progress.
     */
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

    /**
     * Executes the given tasks, returning the result
     * of one that has completed successfully (i.e., without throwing
     * an exception), if any do before the given timeout elapses.
     * Upon normal or exceptional return, tasks that have not
     * completed are cancelled.
     * The results of this method are undefined if the given
     * collection is modified while this operation is in progress.
     *
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

AbstractExecutorService

public abstract class AbstractExecutorService implements ExecutorService {
}

实现 ExecutorService 接口,提供ExecutorService执行方法的默认实现

ThreadPoolExecutor

public class ThreadPoolExecutor extends AbstractExecutorService {
}

线程池的具体实现类,继承自 AbstractExecutorService

类结构图:

ThreadPoolExecutor 使用方法

可以使用工具类 Executors 提供的方法创建线程池,比如:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorServiceTest1 {

    static class MyTask implements Runnable {

        private int i;

        public MyTask(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread() + " 任务" + i);
        }
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        for (int i = 1; i <= 10; i++) {
            executorService.execute(new MyTask(i));
        }
        executorService.shutdown();
    }
}

以上 Executors.newFixedThreadPool 方法创建了一个拥有固定线程数的线城池

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

执行结果:

Thread[pool-1-thread-1,5,main] 任务1
Thread[pool-1-thread-2,5,main] 任务2
Thread[pool-1-thread-2,5,main] 任务4
Thread[pool-1-thread-1,5,main] 任务3
Thread[pool-1-thread-1,5,main] 任务6
Thread[pool-1-thread-2,5,main] 任务5
Thread[pool-1-thread-2,5,main] 任务8
Thread[pool-1-thread-1,5,main] 任务7
Thread[pool-1-thread-2,5,main] 任务9
Thread[pool-1-thread-1,5,main] 任务10

通过结果可以看出,10个任务都是由两个线程执行的,由于这两个线程一次只能处理两个任务,其他任务只有在线程空闲时才能被处理,实际上线程池不仅维护了一组线程的引用,还维护了这组任务,而任务则是放在队列中,即上文的 LinkedBlockingQueue 参数

参考:
https://blog.csdn.net/qq_36881887/article/details/125707550
https://www.mianshigee.com/note/detail/20134hnk/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【c++】数据类型

文章目录整型实型科学计数法sizeof关键字字符型字符串类型转义字符bool布尔类型c规定在创建一个变量或者常量时&#xff0c;必须要指定出相应的数据类型&#xff0c;否则无法给变量分配内存。 整型 作用&#xff1a;整型变量表示的是整数类型的数据。 实型 float f3.14; //默…

JavaCollection集合

5 Collection集合 5.1 Collection集合概述 是单列集合的顶层接口&#xff0c;它表示一组对象&#xff0c;这些对象也称Collection元素JDK不提供此接口的直接实现&#xff0c;它提供更具体的子接口&#xff08;Set 和 List&#xff09;实现 package ceshi;import java.util.A…

【C++1】函数重载,类和对象,引用,/string类,vector容器,类继承和多态,/socket,进程信号

文章目录1.函数重载&#xff1a;writetofile()&#xff0c;Ctrue和false&#xff0c;C0和非02.类和对象&#xff1a;vprintf构造函数&#xff1a;对成员变量初始化析构函数&#xff1a;一个类只有一个&#xff0c;不允许被重载3.引用&#xff1a;C中&取地址&#xff0c;C中…

C语言深度剖析之文件操作

&#x1f497; &#x1f497; 博客:小怡同学 &#x1f497; &#x1f497; 个人简介:编程小萌新 &#x1f497; &#x1f497; 如果博客对大家有用的话&#xff0c;请点赞关注加关注 &#x1f31e; 什么是文件 磁盘上的文件是文件。 但是在程序设计中&#xff0c;我们一般谈的文…

计算机组成原理(四)

1.理解存储器的分类方法&#xff1b;理解存储器的层次结构&#xff1b;熟悉存储器的几个技术指标&#xff08;主要是存储容量、存取时间、存取周期、存储器带宽等&#xff09;&#xff1b; 存储器分类方法&#xff1a;   按与CPU的连接和功能分类&#xff1a;     主存储…

关于HLS直播Buffer PlayQueue多图分析

文章目录前言hls配置m3u8单码流1.开始进入播放页&#xff0c;默认是暂停态2.等几十秒后的状态3.开始播放后的状态其他多码流前言 hls配置 backBufferLength:60 // 默认无限制 缓存媒体播放后要保留的最长持续时间&#xff08;以秒为单位&#xff09;。 liveSyncDurationCount…

【优化算法1】模拟退火算法(含MATLAB实例)

模拟退火算法&#xff08;含MATLAB实例&#xff09;模拟退火算法1.1 简介1.2 原理1.3 MATLAB实例模拟退火算法 1.1 简介 模拟退火算法的思想借鉴于物体退火过程&#xff1a;当温度很高时&#xff0c;物体内能比较大&#xff0c;其内部粒子处于快速无序运动状态&#xff1b;当…

【计算机网络期末复习】第一章 概述

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为想复习学校计算机网络课程的同学提供重点大纲&#xff0c;帮助大家渡过期末考~ &#x1f4da;专栏地址&#xff1a; ❤️如果有收获的话&#xff0c;欢迎点…

第一个C语言代码(visual studin创建调试以及项目文件功能讲解)

这里我主要使用visual Studio进行编程 目录 一.创建项目 二.编写代码 1.代码编写 2.代码分析 3.main() 4.注释符 5.{} 花括号 6.声明 7.赋值 8.printf()函数 9.return 0; 一.创建项目 这里大家可能会比较疑惑&#xff0c;为啥都是C&#xff0c;没看见C的项目&…

C++:AVL树

AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下&#xff0c;时间复杂度为O&#xff08;N&#xff09;&#xff1b; 两位俄罗斯的数学家G.M.Ade…

机试_4_数学问题

在机试中&#xff0c;我们经常会面对这样一类问题&#xff0c;它们并不涉及很深奥的算法和数据结构&#xff0c;而只与数理逻辑相关&#xff0c;将这类题目称为数学问题。 这类问题通常不需要用到特别高深的数学知识&#xff0c;而只需要掌握简单的数理逻辑知识。本文重点记录…

解决访问GitHub时出现的“您的连接不是私密连接”的问题!

Content问题描述解决办法问题描述 访问github出现您的连接不是私密连接问题&#xff0c;无法正常访问&#xff0c;如下图所示&#xff1a; 解决办法 修改hosts文件。hosts文件位于&#xff1a;C:\Windows\System32\drivers\etc\hosts 首先在https://www.ipaddress.com/查找两…

Linux之case语句和循环语句

一、case语句1.case语句的结构case语句主要适用于以下情况&#xff1a;某个变量存在多种取值&#xff0c;需要对其中的每一种取值分别执行不同的命令序列。这种情况与多分支的if语句非常相似&#xff0c;只不过if语句需要判断多个不同的条件&#xff0c;而case语句只是判断一个…

Linux高级命令之查找文件命令

查找文件命令学习目标能够说出查找文件使用的命令1. find命令及选项的使用命令说明find在指定目录下查找文件(包括目录)find命令选项:选项说明-name根据文件名(包括目录名)字查找find命令及选项的效果图:2. find命令结合通配符的使用通配符:是一种特殊语句&#xff0c;主要有星…

Linux中几个在终端中有趣的命令

uhh…最近我不知道该更新些什么&#xff0c;所以就更新Linux几个很有趣的命令 文章目录前言1.命令&#xff1a;sl安装 sl输出2. 命令&#xff1a;telnet命令&#xff1a;fortune安装fortune4.命令&#xff1a;rev&#xff08;反转&#xff09;安装rev5. 命令&#xff1a;factor…

第二章 Opencv图像处理基本操作

目录1.读取图像1-1.imread()方法2.显示图像2-1.imshow()方法2-2.waitKey()方法2-3.destroyAllWindows()方法2-4.小总结3.保存图像3-1.imwrite()方法4.查看图像属性4-1.常见的三个图像属性1.读取图像 要对一幅图像进行处理&#xff0c;第一件事就是要读取这幅图像。 1-1.imread(…

Vue驼峰与短横线分割命名中有哪些坑

目录 0.前言 驼峰和短横线分割命名注意事项 组件注册命名 父子组件数据传递时命名 父子组件函数传递 0.前言 Vue驼峰命名法指的是将变量以驼峰形式命名&#xff0c;例如 userName、userId 等&#xff0c;而短横线分隔符法则指的是用短横线分隔变量名&#xff0c;例如 user…

Python 高级编程之生成器与协程进阶(五)

文章目录一、概述二、生成器1&#xff09;生成器和迭代器的区别2&#xff09;生成器创建方式1、通过生成器函数创建2、通过生成器表达式创建3&#xff09;生成器表达式4&#xff09;yield关键字5&#xff09;生成器函数6&#xff09;return 和 yield 异同7&#xff09;yield的使…

RocketMQ底层源码解——事务消息的实现

1. 简介 RocketMQ自身实现了事务消息&#xff0c;可以通过这个机制来实现一些对数据一致性有强需求的场景&#xff0c;保证上下游数据的一致性。 以电商交易场景为例&#xff0c;用户支付订单这一核心操作的同时会涉及到下游物流发货、积分变更、购物车状态清空等多个子系统…

Linux高级命令之压缩和解压缩命令

压缩和解压缩命令学习目标能够使用tar命令完成文件的压缩和解压缩1. 压缩格式的介绍Linux默认支持的压缩格式:.gz.bz2.zip说明:.gz和.bz2的压缩包需要使用tar命令来压缩和解压缩.zip的压缩包需要使用zip命令来压缩&#xff0c;使用unzip命令来解压缩压缩目的:节省磁盘空间2. ta…