关于java线程池的创建

尾火虎
• 阅读 716

线程池为线程生命周期开销问题和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。其好处是,因为在请求到达时线程已经存在,所以无意中也消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使应用程序响应更快。而且,通过适当地调整线程池中的线程数目,也就是当请求的数目超过某个阈值时,就强制其它任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。

使用spring管理线程池的使用


1、创建线程池的配置信息threads.properties

####业务线程池配置####
#是否启用自定义线程池。true时启动,以下参数生效
handler.threads.custom=false
#核心线程数
handler.threads.corePoolSize=20
#最大线程数
handler.threads.maximumPoolSize=1000
#空闲线程存活时间,单位秒
handler.threads.keepAliveTime=100
#工作队列大小,为0是无限大
handler.threads.workQueue=0

2、创建 线程池 配置,ThreadsPoolConfig.java

package com.hk.core.concurrent;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


/**
 * 线程池 配置
 */
@Component
public class ThreadsPoolConfig {

    /**
     * 是否开启自定义线程池
     */
    @Value("${handler.threads.custom}")
    private boolean custom;
    /**
     * 核心线程数
     */
    @Value("${handler.threads.corePoolSize}")
    private int corePoolSize;
    /**
     * 线程池最大线程数
     */
    @Value("${handler.threads.maximumPoolSize}")
    private int maximumPoolSize;
    /**
     * 空闲线程存活时间(对核心线程无效)
     */
    @Value("${handler.threads.keepAliveTime}")
    private long keepAliveTime;
    /**
     * 任务队列大小,0时为无界队列
     */
    @Value("${handler.threads.workQueue}")
    private int workQueue;

    public boolean isCustom() {
        return custom;
    }

    public void setCustom(boolean custom) {
        this.custom = custom;
    }

    public int getCorePoolSize() {
        return corePoolSize;
    }

    public void setCorePoolSize(int corePoolSize) {
        this.corePoolSize = corePoolSize;
    }

    public int getMaximumPoolSize() {
        return maximumPoolSize;
    }

    public void setMaximumPoolSize(int maximumPoolSize) {
        this.maximumPoolSize = maximumPoolSize;
    }

    public long getKeepAliveTime() {
        return keepAliveTime;
    }

    public void setKeepAliveTime(long keepAliveTime) {
        this.keepAliveTime = keepAliveTime;
    }

    public int getWorkQueue() {
        return workQueue;
    }

    public void setWorkQueue(int workQueue) {
        this.workQueue = workQueue;
    }
    
}

3、创建 线程池 处理器管理线程 HandlerThreadsPool.java

package com.hk.core.concurrent;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.annotation.PreDestroy;

/**
 * 线程管理器
 */
public class HandlerThreadsPool {

    public ExecutorService executorService;
    
    public HandlerThreadsPool() {
        // TODO Auto-generated constructor stub
        this.executorService=Executors.newCachedThreadPool();
    }
    
    public HandlerThreadsPool(ThreadsPoolConfig config) {
        // TODO Auto-generated constructor stub
        if(config.isCustom()){
            BlockingQueue<Runnable> queue=null;
            if(config.getWorkQueue()>0){
                queue=new LinkedBlockingQueue<Runnable>(config.getWorkQueue()); // 一般使用 LinkedBlockingQueue 队列
            }else{
                queue=new LinkedBlockingQueue<Runnable>();
            }        // 配置线程池信息
            this.executorService=new ThreadPoolExecutor(
                    config.getCorePoolSize(), 
                    config.getMaximumPoolSize(), 
                    config.getKeepAliveTime(), 
                    TimeUnit.SECONDS, 
                    queue, 
                    new ThreadPoolExecutor.AbortPolicy()//拒绝策略,任务队列满后,新的任务将被丢弃,并抛出异常
                    );
        }else{
            this.executorService=Executors.newCachedThreadPool();
        }
    }     /*   * 创建线程,对线程处理事件     */
    public void execute(Runnable runnable){
        executorService.execute(runnable);
    }
    
        
    /*   * 对象销毁时,销毁线程   */
    @PreDestroy
    public void stop() {
        executorService.shutdown(); 
    }
    
}

4、使用线程池

package com.hk.core.concurrent;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MsgHandler implements Runnable{

    
    @Autowired
    private  ThreadsPoolConfig config;  // 注入 配置
    
    @Override
    public void run() {
       // do 这里 写 处理的逻辑
        System.out.println("创建线程 处理事务....");
    }

    
    @PostConstruct
    public void loadThreadsPool(){
        
        // 初始化 线程池
        HandlerThreadsPool handlerThreadsPool=new HandlerThreadsPool(config); 
        
        //调用线程池,创建线程  。处理事件
        handlerThreadsPool.execute(new MsgHandler());
    }
}

关系中断线程的使用(简略)

//线程,可用于固定线程池大小,重复动作使用某个线程强制停止
        new Thread(() -> {

        },"线程名称").start();
//方法
    private static boolean threadIsRunning() {
        boolean flag = false;
        //getAllStackTraces()方法的作用是返回所有活动线程的堆栈跟踪的一个映射。映射键是线程,而每个映 射值都是一个 StackTraceElement 数组,该数组表示相应Thread的堆栈转 储。返回的堆栈跟踪的格式都是针对getStackTrace方法指定的。在调用该 方法的同时,线程可能也在执行。每个线程的堆栈跟踪仅代表一个快照, 并且每个堆栈跟踪都可以在不同时间获得。如果虚拟机没有线程的堆栈跟 踪信息,则映射值中将返回一个零长度数组。
        for (Thread t : Thread.getAllStackTraces().keySet()) {
            if ("线程名称".equals(t.getName())) {
                LOG.info("正在发送上一线程中断指令...");
        //interrupt()方法的作用是中断对应的线程
                t.interrupt();
                LOG.info("已发送中断指令");
                flag = true;
            }
        }
        return flag;
    }
点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
4年前
java 面试知识点笔记(十三)多线程与并发
java线程池,利用Exceutors创建不同的线程池满足不同场景需求:1.newSingleThreadExecutor() 创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。2.
Wesley13 Wesley13
4年前
java各种面试问题
二、Java多线程相关线程池的原理,为什么要创建线程池?创建线程池的方式;线程的生命周期,什么时候会出现僵死进程;说说线程安全问题,什么实现线程安全,如何实现线程安全;创建线程池有哪几个核心参数?如何合理配置线程池的大小?volatile、ThreadLocal的使用场景和原理;
Wesley13 Wesley13
4年前
java四大线程池
一、为什么需要使用线程池  1、减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。2、可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。Java中创建和销毁一个线程是比较
Stella981 Stella981
4年前
Executor线程池
线程池为线程生命周期的开销和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。_0_|_1_线程实现方式Thread、Runnable、Callable//实现Runnable接口的类将被Thread执行,表示一个基本任务p
Wesley13 Wesley13
4年前
Java 线程池
线程池用的比较多。参考文章http://blog.csdn.net/sd0902/article/details/8395677线程的优点1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程
Wesley13 Wesley13
4年前
Java 线程池原理分析
1.简介线程池可以简单看做是一组线程的集合,通过使用线程池,我们可以方便的复用线程,避免了频繁创建和销毁线程所带来的开销。在应用上,线程池可应用在后端相关服务中。比如Web服务器,数据库服务器等。以Web服务器为例,假如Web服务器会收到大量短时的HTTP请求,如果此时我们简单的为每个HTTP请求创建一个处理线程,那么服务器
Stella981 Stella981
4年前
Noark入门之线程模型
0x00单线程多进程单线程与单进程多线程的目的都是想尽可能的利用CPU,减少CPU的空闲时间,特别是多核环境,今天咱不做深度解读,跳过...0x01线程池锁最早的一部分游戏服务器是采用线程池的方式来处理玩家的业务请求,以达最大限度的利用多核优势来提高处理业务能力。但线程池同时也带来了并发问题,为了解决同一玩家多个业务请求不被
Wesley13 Wesley13
4年前
Java ExecutorService四种线程池及ThreadPoolExecutor机制
一、为什么使用线程池使用newThread执行多个线程有如下一些问题:每次newThread新建对象性能差。线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。缺乏更多功能,如定时执行、定期执行、线程中断。相比newThread,Java提供的四种线程池的好处在于:重用存在的线程,减
Wesley13 Wesley13
4年前
Java中的线程池
java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过程中,合理使用线程池能够带来三个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。第三:提高线程的可管理性。线程是稀缺
ThreadPoolExecutor线程池内部处理浅析 | 京东物流技术团队
我们知道如果程序中并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束时,会因为频繁创建线程而大大降低系统的效率,因此出现了线程池的使用方式,它可以提前创建好线程来执行任务。本文主要通过java的ThreadPoolExecutor来查看线程池
小万哥 小万哥
1年前
深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践
Java线程线程使程序能够通过同时执行多个任务而更有效地运行。线程可用于在不中断主程序的情况下在后台执行复杂的任务。创建线程有两种创建线程的方式。1.扩展Thread类可以通过扩展Thread类并覆盖其run()方法来创建线程:javapublicclas