手把手教你做一个java线程池小例子
手动创建线程池案例
手动创建线程池案例咱来搞一个手动创建线程池的小案例哈。
首先呢,在Java里创建线程池得引入`java.util.concurrent`这个包,这里面有好多和并发相关的好东西。
咱先定义一个线程池,就像打造一个小团队一样。
使用`ExecutorService`来创建线程池,比如说用`ThreadPoolExecutor`这个类。
它就像一个超级管理员,可以管理很多小工(线程)干活。
java.import java.util.concurrent.ExecutorService;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ThreadPoolExample {public static void main(String[] args) {// 创建一个线程池,这里面的参数都有特殊含义哦。
// 第一个参数是核心线程数,就像一个公司一直保留的正式员工数量。
// 第二个参数是最大线程数,忙的时候可以临时扩招到这么多员工。
// 第三个参数是空闲线程存活时间,没事干的小工(线程)能等多久才被解雇。
// 第四个参数是存活时间的单位,像秒啊分钟啊啥的。
// 第五个参数是一个阻塞队列,用来存放等待执行的任务,就像任务的等候室。
ExecutorService executor = new ThreadPoolExecutor(2, // 核心线程数为2。
5, // 最大线程数为5。
10, TimeUnit.SECONDS, // 空闲线程存活10秒。
new java.util.concurrent.LinkedBlockingQueue<>());// 现在咱有一些任务要交给这个线程池里的小工(线程)去做啦。
for (int i = 0; i < 10; i++) {final int taskNumber = i;executor.execute(() -> {System.out.println("正在执行任务 " + taskNumber + ",线程名字是 " + Thread.currentThread().getName());});}// 所有任务都交出去了,咱得告诉这个线程池管理员(ExecutorService)别再接新任务啦。
Java自定义线程池的实现示例
Java⾃定义线程池的实现⽰例⽬录⼀、Java语⾔本⾝也是多线程,回顾Java创建线程⽅式如下:⼆、JDK线程池⼯具类.三、业界知名⾃定义线程池扩展使⽤.⼀、Java语⾔本⾝也是多线程,回顾Java创建线程⽅式如下:1、继承Thread类,(Thread类实现Runnable接⼝),来个类图加深印象。
2、实现Runnable接⼝实现⽆返回值、实现run()⽅法,啥时候run,⿊话了。
3、实现Callable接⼝重写call()+FutureTask获取.public class CustomThread {public static void main(String[] args) {// ⾃定义线程new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Custom Run");System.out.println(Thread.currentThread().getName());}},"custom-thread-1").start();}}4、基于线程池集中管理创建线程系列周期.【本篇⽂章重点介绍】⼆、JDK线程池⼯具类.1、Executors⼯具类,是JDK中Doug Lea⼤佬实现供开发者使⽤。
随着JDK版本迭代逐渐加⼊了基于⼯作窃取算法的线程池了,阿⾥编码规范也推荐开发者⾃定义线程池,禁⽌⽣产直接使⽤Executos线程池⼯具类,因此很有可能造成OOM异常。
同时在某些类型的线程池⾥⾯,使⽤⽆界队列还会导致maxinumPoolSize、keepAliveTime、handler等参数失效。
因此⽬前在⼤⼚的开发规范中会强调禁⽌使⽤Executors来创建线程池。
这⾥说道阻塞队列。
LinkedBlockingQueue。
2、⾃定义线程池⼯具类基于ThreadPoolExecutor实现,那个JDK封装的线程池⼯具类也是基于这个ThreadPoolExecutor实现的。
java实现手写一个简单版的线程池
java实现⼿写⼀个简单版的线程池有些⼈可能对线程池⽐较陌⽣,并且更不熟悉线程池的⼯作原理。
所以他们在使⽤线程的时候,多数情况下都是new Thread来实现多线程。
但是,往往良好的多线程设计⼤多都是使⽤线程池来实现的。
为什么要使⽤线程降低资源的消耗。
降低线程创建和销毁的资源消耗。
提⾼响应速度:线程的创建时间为T1,执⾏时间T2,销毁时间T3,免去T1和T3的时间提⾼线程的可管理性下图所⽰为线程池的实现原理:调⽤⽅不断向线程池中提交任务;线程池中有⼀组线程,不断地从队列中取任务,这是⼀个典型的⽣产者-消费者模型。
要实现⼀个线程池,有⼏个问题需要考虑:队列设置多长?如果是⽆界的,调⽤⽅不断往队列中⽅任务,可能导致内存耗尽。
如果是有界的,当队列满了之后,调⽤⽅如何处理?线程池中的线程个数是固定的,还是动态变化的?每次提交新任务,是放⼊队列?还是开新线程当没有任务的时候,线程是睡眠⼀⼩段时间?还是进⼊阻塞?如果进⼊阻塞,如何唤醒?针对问题4,有3种做法:不使⽤阻塞队列,只使⽤⼀般的线程安全的队列,也⽆阻塞/唤醒机制。
当队列为空时,线程池中的线程只能睡眠⼀会⼉,然后醒来去看队列中有没有新任务到来,如此不断轮询。
不使⽤阻塞队列,但在队列外部,线程池内部实现了阻塞/唤醒机制使⽤阻塞队列很显然,做法3最完善,既避免了线程池内部⾃⼰实现阻塞/唤醒机制的⿇烦,也避免了做法1的睡眠/轮询带来的资源消耗和延迟。
现在来带⼤家⼿写⼀个简单的线程池,让⼤家更加理解线程池的⼯作原理实战:⼿写简易线程池根据上图可以知道,实现线程池需要⼀个阻塞队列+存放线程的容器/*** Five在努⼒* ⾃定义线程池*/public class ThreadPool {/** 默认线程池中的线程的数量 */private static final int WORK_NUM = 5;/** 默认处理任务的数量 */private static final int TASK_NUM = 100;/** 存放任务 */private final BlockingQueue<Runnable> taskQueue;private final Set<WorkThread> workThreads;//保存线程的集合private int workNumber;//线程数量private int taskNumber;//任务数量public ThreadPool(){this(WORK_NUM , TASK_NUM);}public ThreadPool(int workNumber , int taskNumber) {if (taskNumber<=0){taskNumber = TASK_NUM;}if (workNumber<=0){workNumber = WORK_NUM;}this.taskQueue = new ArrayBlockingQueue<Runnable>(taskNumber);this.workNumber = workNumber;this.taskNumber = taskNumber;workThreads = new HashSet<>();//⼯作线程准备好了//启动⼀定数量的线程数,从队列中获取任务处理for (int i=0;i<workNumber;i++) {WorkThread workThread = new WorkThread("thead_"+i);workThread.start();workThreads.add(workThread);}}/*** 线程池执⾏任务的⽅法,其实就是往BlockingQueue中添加元素* @param task*/public void execute(Runnable task) {try {taskQueue.put(task);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 销毁线程池*/public void destroy(){System.out.println("ready close pool...");for (WorkThread workThread : workThreads) {workThread.stopWorker();workThread = null;//help gc}workThreads.clear();}/** 内部类,⼯作线程的实现 */private class WorkThread extends Thread{public WorkThread(String name){super();setName(name);}@Overridepublic void run() {while (!interrupted()) {try {Runnable runnable = taskQueue.take();//获取任务if (runnable !=null) {System.out.println(getName()+" ready execute:"+runnable.toString());runnable.run();//执⾏任务}runnable = null;//help gc} catch (Exception e) {interrupt();e.printStackTrace();}}}public void stopWorker(){interrupt();}}}上⾯代码定义了默认的线程数量和默认处理任务数量,同时⽤户也可以⾃定义线程数量和处理任务数量。
java线程池用法
java线程池用法Java线程池是Java中的一个重要概念,它可以帮助我们更好地管理线程,提高程序的性能和可靠性。
本文将介绍Java线程池的用法,包括线程池的创建、使用和销毁等方面。
一、线程池的创建Java线程池的创建非常简单,只需要使用ThreadPoolExecutor类即可。
ThreadPoolExecutor类是Java中的一个线程池类,它提供了一些方法来创建和管理线程池。
下面是一个简单的线程池创建示例: ```javaExecutorService executor = Executors.newFixedThreadPool(10);```上面的代码创建了一个固定大小为10的线程池。
这个线程池可以同时执行10个任务,如果有更多的任务需要执行,它们将会被放入一个队列中等待执行。
二、线程池的使用线程池的使用非常简单,只需要将任务提交给线程池即可。
下面是一个简单的线程池使用示例:```javaexecutor.submit(new Runnable() {public void run() {// 执行任务}});```上面的代码将一个Runnable对象提交给线程池,线程池会自动分配一个线程来执行这个任务。
如果线程池中没有空闲的线程,这个任务将会被放入队列中等待执行。
三、线程池的销毁线程池的销毁非常重要,如果不及时销毁线程池,会导致程序的性能和可靠性下降。
下面是一个简单的线程池销毁示例:```javaexecutor.shutdown();```上面的代码将会销毁线程池,它会等待所有任务执行完毕后再销毁线程池。
如果你想立即销毁线程池,可以使用下面的代码:```javaexecutor.shutdownNow();```上面的代码会立即销毁线程池,它会尝试中断所有正在执行的任务。
四、线程池的优点Java线程池有很多优点,下面是一些主要的优点:1. 提高程序的性能:线程池可以重复利用线程,避免了线程的创建和销毁,从而提高了程序的性能。
java创建线程池的三种方法
java创建线程池的三种方法一、使用ThreadPoolExecutor类创建线程池ThreadPoolExecutor是Java提供的一个线程池实现类,通过它可以方便地创建一个线程池。
ThreadPoolExecutor提供了丰富的参数和方法来满足不同的需求。
创建ThreadPoolExecutor的方式一般有两种,一种是直接创建ThreadPoolExecutor的实例,另一种是通过Executors工厂类提供的静态方法来创建。
1. 直接创建ThreadPoolExecutor实例可以通过构造函数来创建ThreadPoolExecutor实例,构造函数的参数包括核心线程数、最大线程数、线程空闲时间、任务队列等。
示例代码如下:```javaThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, // 核心线程数maximumPoolSize, // 最大线程数keepAliveTime, // 线程空闲时间TimeUnit.SECONDS, // 时间单位workQueue // 任务队列);```2. 使用Executors工厂类创建ThreadPoolExecutor实例Executors工厂类提供了一些静态方法来创建ThreadPoolExecutor 实例,比如newFixedThreadPool、newCachedThreadPool等。
示例代码如下:```javaExecutorService executor = Executors.newFixedThreadPool(nThreads); // 创建固定大小的线程池ExecutorService executor = Executors.newCachedThreadPool(); // 创建可缓存的线程池```二、使用ScheduledThreadPoolExecutor类创建定时线程池ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类,它专门用于创建定时线程池。
java线程池使用案例
java线程池使用案例在Java编程中,线程池是一种重要的多线程处理机制。
它可以有效地管理和复用线程,提高程序的性能和效率。
本文将介绍一个使用Java线程池的案例。
假设我们有一个需求,需要从一个文件夹中读取多个文件,并对每个文件进行处理。
由于文件的数量可能很大,为了提高处理速度,我们可以使用线程池来并发处理这些文件。
首先,我们需要创建一个线程池。
在Java中,可以使用ThreadPoolExecutor类来创建线程池。
下面是创建线程池的代码:```javaint corePoolSize = 5; // 核心线程数int maximumPoolSize = 10; // 最大线程数long keepAliveTime = 5000; // 线程空闲时间TimeUnit unit = LISECONDS; // 时间单位BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(); // 任务队列ExecutorService executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);```上述代码中,我们创建了一个核心线程数为5,最大线程数为10的线程池。
线程空闲时间为5000毫秒,任务队列使用了一个无界的LinkedBlockingQueue。
接下来,我们需要定义一个任务类,用于处理文件。
假设我们的文件处理逻辑是将文件内容转换为大写,并输出到控制台。
下面是任务类的代码:```javaclass FileTask implements Runnable {private String filePath;public FileTask(String filePath) {this.filePath = filePath;}@Overridepublic void run() {try {// 读取文件内容String content = readFile(filePath);// 转换为大写String upperCaseContent = content.toUpperCase();// 输出到控制台System.out.println(upperCaseContent);} catch (IOException e) {e.printStackTrace();}}private String readFile(String filePath) throws IOException {// 读取文件内容的逻辑// ...}}```在任务类中,我们实现了Runnable接口,并重写了run方法。
java线程池的使用例子
java线程池的使用例子随着计算机技术的不断发展,我们的软件系统越来越复杂,需要同时处理大量的任务。
在这种情况下,多线程编程成为了一种必不可少的技术手段。
但是,如果不加以控制,多线程编程可能会带来很多问题,比如线程数量过多、线程创建和销毁造成的开销、线程间通信的复杂性等等。
为了解决这些问题,Java提供了线程池技术。
本文将介绍Java线程池的使用例子。
1. 线程池的基本概念线程池是一种线程管理技术,它维护一定数量的线程,让它们在需要的时候执行任务。
线程池的好处在于可以减少线程创建和销毁的开销,避免线程数量过多导致系统资源不足,提高系统的稳定性和性能。
Java中的线程池是通过java.util.concurrent包下的ThreadPoolExecutor类实现的。
ThreadPoolExecutor类是一个线程池的实现,它提供了一些方法来管理线程池的状态和行为。
ThreadPoolExecutor类的构造方法如下:public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)其中,参数的含义如下:- corePoolSize:线程池中核心线程的数量。
- maximumPoolSize:线程池中最大线程的数量。
- keepAliveTime:非核心线程的空闲时间。
- unit:keepAliveTime的时间单位。
- workQueue:任务队列,用于保存还未执行的任务。
- threadFactory:线程工厂,用于创建新的线程。
- handler:饱和策略,用于处理任务队列已满的情况。
Java之线程池简单实现
Java之线程池简单实现线程池的技术背景在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。
在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。
所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。
如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因。
多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。
但如果对多线程应用不当,会增加对单个任务的处理时间。
可以举一个简单的例子:假设在一台服务器完成一项任务的时间为T◆ T1 创建线程的时间◆ T2 在线程中执行任务的时间,包括线程间同步所需时间◆ T3 线程销毁的时间显然T = T1+T2+T3。
注意这是一个极度简化的假设。
可以看出T1,T3是多线程本身的带来的开销,我们渴望减少T1,T3所用的时间,从而减少T的时间。
但一些线程的使用者并没有注意到这一点,所以在程序中频繁的创建或销毁线程,这导致T1和T3在T中占有相当比例。
显然这是突出了线程的弱点(T1,T3),而不是优点(并发性)。
线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。
它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。
线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目。
在看一个例子:假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成。
我们比较利用线程池技术和不利于线程池技术的服务器处理这些请求时所产生的线程总数。
在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程的数目或者上限(以下简称线程池尺寸),而如果服务器不利用线程池来处理这些请求则线程总数为50000。
java线程池executor案例
java线程池executor案例1. 引言1.1 概述引言部分旨在介绍本篇文章的主题:Java线程池Executor。
在当今互联网时代,处理并发任务是软件开发中一个重要的挑战。
为了提高系统的性能和效率,并发编程虽然有着巨大的潜力,却也面临着一系列问题和难题。
为解决这些问题,Java 引入了线程池Executor框架,它提供了一种管理和调度多个线程执行任务的机制,极大地简化了并发编程的复杂性。
1.2 文章结构本篇文章将围绕着Java线程池Executor展开详细阐述。
具体来说,将包括以下几个方面内容:首先,在第2部分中,我们将介绍线程池的基础概念,探讨什么是线程池、线程池的优点和用途以及其组成和工作原理;接下来,在第3部分中,我们将深入研究Java线程池的用法,包括如何创建线程池、如何向线程池提交任务以及如何控制线程池的大小和任务队列策略;在第4部分,则会对Executor 框架进行详解,包括Executor接口、ExecutorService接口、ThreadPoolExecutor类和ScheduledThreadPoolExecutor类的介绍,以及Callable、Future和CompletionService等类的使用方法;最后,在第5部分中,我们将通过实际案例分析来展示如何使用线程池处理并发任务,包括基本示例、定时器和计划任务的高级示例,以及使用ForkJoinPool实现分治计算的高级示例。
1.3 目的本文旨在向读者全面详细地介绍Java线程池Executor框架,并通过实际案例解析展示其应用。
通过阅读本文,读者将能够理解线程池的基础概念、掌握Java 线程池的用法、了解Executor框架的原理和功能,并能够运用所学知识处理并发任务。
无论是初学者还是有一定经验的开发人员,都能从本文中收获对于并发编程更深入的理解和应用能力。
2. 线程池基础概念:2.1 什么是线程池?线程池是一种可以管理和控制多个线程的机制,它能够帮助我们高效地处理并发任务。
java多线程简单例子
//重写run方法, public void run(){
while(ticket>0){ synchronized (Booking.class) { if (ticket>0) { System.out.println(super.getName()+"窗口---->卖出的车票号No."+ticket); ticket--; }else { System.out.println(super.getName()+"票已售罄!!!"); } try { sleep(100);//睡100毫秒,抛出多线程异常 } catch (InterruptedException e) { e.printStackTrace(); } } /*lock.lock();//加锁,锁定以下代码 if (ticket>0) { System.out.println(super.getName()+"卖票:"+ticket); ticket--;
/* * ReentrantLock根据传入构造方法的布尔型参数实例化出Sync的实现类FairSync和NonfairSync * ,分别表示公平的Sync和非公平的Sync。 * 由于ReentrantLocபைடு நூலகம்我们用的比较多的是非公平锁
ReentrantLock 和synchronized 均为重入锁
/* * 多窗口卖票系统。多线程 * 票数为静态的,共享数据 * synchronized(对象){}代码块中的内容是加锁的, * 即当一个线程在使用时,其他线程不可以进入。 * 使得共享资源数据的安全。 */ class Booking extends Thread{ public Booking(String name){ super(name); } static int ticket = 50;//票数共50张 Lock lock = new ReentrantLock();//明锁
线程池实际案例使用
线程池实际案例使用全文共四篇示例,供读者参考第一篇示例:随着互联网和移动互联网的发展,线程池成为了开发中常用的一种机制。
线程池的作用是管理、控制和复用线程,避免了频繁创建和销毁线程的开销,提高了并发性能和资源利用率。
在实际的开发中,线程池被广泛应用于网络编程、并发处理、数据库连接池等场景。
下面我们来看一些线程池的实际案例使用。
一、网络编程在网络编程中,通常会使用线程池来处理多个客户端的请求。
比如一个简单的网络服务器,可以通过线程池来处理客户端发来的请求,每个客户端连接后就会分配一个线程来处理。
这样可以避免每个客户端连接都创建一个线程,提高服务器的性能和稳定性。
二、并发处理在一些需要并发处理大量任务的场景中,线程池也非常有用。
比如在一个电商网站中,有大量的订单需要处理,可以使用线程池来对订单进行并发处理,每个订单分配一个线程来处理,同时限制线程数量,避免资源被耗尽。
这样可以提高订单处理的效率,并且保证系统的稳定性。
三、数据库连接池数据库连接通常是一种昂贵的资源,为了减少数据库连接的开销,可以使用线程池来管理数据库连接。
通过线程池可以复用数据库连接,避免频繁地建立和断开连接。
在实际开发中,我们可以使用开源框架如c3p0、Druid等来实现数据库连接池,这些框架提供了丰富的配置选项和监控功能,可以方便地管理数据库连接。
四、任务调度线程池也可以用于任务调度,比如定时任务、周期性任务等。
我们可以使用Java自带的ScheduledThreadPoolExecutor来实现这些功能,通过线程池来管理定时任务的执行。
这样可以避免手动创建线程来执行定时任务,提高了代码的可维护性和可读性。
以上是线程池在实际开发中的一些应用场景,线程池在提高系统性能、减少资源开销、保证系统稳定性等方面发挥了重要作用。
在使用线程池时,需要根据具体的业务需求和场景来合理配置线程池的参数,避免线程池过大导致资源浪费,或者线程池过小导致任务阻塞。
java 线程池实用案例
java 线程池实用案例Java线程池是一种重要的并发编程工具,它可以有效地管理和复用线程,提高程序的性能和资源利用率。
下面我将从多个角度给出一些Java线程池的实用案例。
1. 网络编程,在网络编程中,通常需要处理大量的并发请求,使用线程池可以有效地管理客户端的连接请求。
比如,一个基于TCP协议的服务器程序可以使用线程池来处理客户端的连接请求,每当有新的连接请求到来时,线程池会分配一个空闲线程来处理该请求,这样就能够避免频繁地创建和销毁线程,提高了服务器的性能和稳定性。
2. 数据库访问,在访问数据库时,线程池可以用于处理大量的数据库查询和更新操作。
通过线程池,可以限制并发访问数据库的线程数量,避免对数据库造成过大的压力,提高数据库的响应速度和稳定性。
3. 定时任务,线程池还可以用于执行定时任务。
比如,可以使用ScheduledThreadPoolExecutor来执行定时的数据备份、日志清理等任务,通过合理配置线程池的大小和任务调度策略,可以有效地管理定时任务的执行。
4. 并行计算,在一些需要进行大量计算的场景中,可以使用线程池来进行并行计算,提高计算速度。
比如,可以将一个大型的计算任务拆分成多个子任务,然后提交给线程池进行并行处理,最后将结果合并得到最终的计算结果。
5. GUI应用程序,在GUI应用程序中,使用线程池可以避免在主线程中进行耗时的操作,从而保持界面的流畅性。
比如,可以使用线程池来处理后台的数据加载、图片下载等操作,以提高用户体验。
总的来说,Java线程池在各种并发场景下都有着广泛的应用。
合理地使用线程池可以提高程序的性能、资源利用率和稳定性,是并发编程中的重要工具之一。
希望以上实用案例能够帮助你更好地理解和应用Java线程池。
JAVA线程池实现实例
java线程池实现实例线程池作用就是限制系统中执行线程的数量。
根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。
用线程池控制线程数量,其他线程排队等候。
一个任务执行完毕,再从队列的中取最前面的任务开始执行。
若队列中没有等待进程,线程池的这一资源处于等待。
当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。
为什么要用线程池:1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)线程池类Java代码1.package com.tdt.impl.ls;2.3.import java.util.LinkedList;4.5./**6.*@project LocationGateway7.*@author sunnylocus8.*@verson 1.0.09.*@date Aug2,200810.*@jdk 1.4.211.*/12.public class ThreadPool extends ThreadGroup{13.private boolean isClosed=false;//线程池是否关闭14.private LinkedList workQueue;//工作队列15.private static int threadPoolID=1;//线程池的id16.public ThreadPool(int poolSize){//poolSize表示线程池中的工作线程的数量17.18.super(threadPoolID+"");//指定ThreadGroup的名称19.setDaemon(true);//继承到的方法,设置是否守护线程池20.workQueue=new LinkedList();//创建工作队列21.for(int i=0;i<poolSize;i++){22.new WorkThread(i).start();//创建并启动工作线程,线程池数量是多少就创建多少个工作线程23.}24.}25.26./**向工作队列中加入一个新任务,由工作线程去执行该任务*/27.public synchronized void execute(Runnable task){28.if(isClosed){29.throw new IllegalStateException();30.}31.if(task!=null){32.workQueue.add(task);//向队列中加入一个任务33.notify();//唤醒一个正在getTask()方法中待任务的工作线程34.}35.}36.37./**从工作队列中取出一个任务,工作线程会调用此方法*/38.private synchronized Runnable getTask(int threadid)throws InterruptedException{39.while(workQueue.size()==0){40.if(isClosed)return null;41.System.out.println("工作线程"+threadid+"等待任务...");42.wait();//如果工作队列中没有任务,就等待任务43.}44.System.out.println("工作线程"+threadid+"开始执行任务...");45.return(Runnable)workQueue.removeFirst();//反回队列中第一个元素,并从队列中删除46.}47.48./**关闭线程池*/49.public synchronized void closePool(){50.if(!isClosed){51.waitFinish();//等待工作线程执行完毕52.isClosed=true;53.workQueue.clear();//清空工作队列54.interrupt();//中断线程池中的所有的工作线程,此方法继承自ThreadGroup类55.}56.}57.58./**等待工作线程把所有任务执行完毕*/59.public void waitFinish(){60.synchronized(this){61.isClosed=true;62.notifyAll();//唤醒所有还在getTask()方法中等待任务的工作线程63.}64.Thread[]threads=new Thread[activeCount()];//activeCount()返回该线程组中活动线程的估计值。
JAVA线程池介绍以及简单实例
JAVA线程池介绍以及简单实例文章分类:Java编程在什么情况下使用线程池?1.单个任务处理的时间比较短2.将需处理的任务的数量大使用线程池的好处:1.减少在创建和销毁线程上所花的时间以及系统资源的开销2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”。
线程池工作原理:/developerworks/cn/java/j-jtp0730/该文章里有个例子,简单的描述了线程池的内部实现,建议根据里面的例子来了解JAVA 线程池的原理。
同时,里面还详细描述了使用线程池存在的优点和弊端,大家可以研究下,我觉得是篇非常好的文章。
JDK自带线程池总类介绍介绍:1、newFixedThreadPool创建一个指定工作线程数量的线程池。
每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
2、newCachedThreadPool创建一个可缓存的线程池。
这种类型的线程池特点是:1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。
终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
3、newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。
单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
4、newScheduleThreadPool创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。
(这种线程池原理暂还没完全了解透彻)总结:一.FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。
简单多任务线程池版例子
简单多任务线程池版例子线程池是一种用于管理和重复使用线程的技术,它可以提高多任务处理的效率。
下面我将给出一个简单的多任务线程池的示例。
java.import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadPoolExample {。
public static void main(String[] args) {。
// 创建一个固定大小为5的线程池。
ExecutorService executor =Executors.newFixedThreadPool(5);// 提交10个任务给线程池处理。
for (int i = 0; i < 10; i++) {。
Runnable task = new Task(i); executor.submit(task);}。
// 关闭线程池。
executor.shutdown();}。
}。
class Task implements Runnable {。
private int taskId;public Task(int id) {。
this.taskId = id;}。
@Override.public void run() {。
System.out.println("Task ID : " + this.taskId + " 执行中,线程名为," + Thread.currentThread().getName());try {。
Thread.sleep(2000);} catch (InterruptedException e) {。
e.printStackTrace();}。
System.out.println("Task ID : " + this.taskId + " 已完成");}。
创建线程池的几种方法
创建线程池的几种方法《嘿,创建线程池的几种超有趣方法》嘿,朋友!今天咱来唠唠创建线程池的几种方法哈,这可都是我的独家秘籍哦!首先呢,咱得知道啥是线程池。
你就把它想象成一个超级勤劳的小团队,专门帮咱处理各种任务,而且还特别高效!第一种方法呢,就像是给这个小团队找了个厉害的领队。
咱要设置好线程池的核心参数,比如线程数量啥的。
这就好比给小团队规定好有几个干活的,不能太多也不能太少,多了容易乱套,少了又干不过来活儿。
我给你讲个奇葩经历哈,有次我就没设置好这个参数,结果弄出一堆线程来,就像一群无头苍蝇到处乱撞,那场面,简直了!然后呢,咱要把任务交给这个小团队。
就像是给他们发工单一样,告诉他们要干啥。
这一步可得仔细咯,可别把任务交代错了,不然他们干错了活儿可别怪我没提醒你哦!再来说说第二种方法,这就像给小团队升级装备一样。
咱可以根据不同的任务类型,设置不同的线程池策略。
比如说,有些任务特别紧急,那就得给它们开个快速通道,让它们优先处理。
我记得有一次,有个特别重要的任务,我就没设置好策略,结果它在那慢悠悠地排队,差点把我急死!还有一种方法也挺有意思,就好像给小团队找了几个特别厉害的专家。
就是利用一些现成的框架和库来创建线程池。
这可省了咱不少事儿呢,人家都给咱弄好了,咱直接用就行。
但是哈,这里也有个要注意的地方,就像你请专家来帮忙,也得搞清楚他们擅长啥,可别瞎用哦!总结一下哈,创建线程池就这么几步:首先找好领队,设置好参数;然后发好工单,交代任务;接着根据情况升级装备或者找专家帮忙。
哎呀,你可别小看这几步,弄好了那效率蹭蹭往上涨,弄不好可就麻烦啦!就像那句话说的,“细节决定成败”。
朋友,听我这么一说,是不是觉得创建线程池也没那么难啦?赶紧去试试吧,等你成功了,可别忘了回来跟我分享分享哦!哈哈!好啦,今天就唠到这儿,下次再给你分享别的好玩儿的。
java11的线程池写法
java11的线程池写法在Java 11中,线程池的写法可以通过使用`Executors`工厂类来创建不同类型的线程池。
下面我将介绍一些常见的线程池写法。
1. 创建固定大小的线程池:java.ExecutorService executor =Executors.newFixedThreadPool(5);这将创建一个固定大小为5的线程池,线程池中的线程数量始终保持不变,当有新任务提交时,如果线程池中有空闲线程,则立即执行,如果没有,则新任务会被暂存在一个任务队列中,待有线程空闲时再执行。
2. 创建单线程的线程池:java.ExecutorService executor =Executors.newSingleThreadExecutor();这将创建一个只有一个工作线程的线程池,所有任务按照它们被提交的顺序依次执行。
3. 创建可缓存的线程池:java.ExecutorService executor =Executors.newCachedThreadPool();这将创建一个可根据需要创建新线程的线程池,而且在先前构建的线程可用时将重用它们。
如果线程在60秒内未被使用,则将终止并从缓存中移除。
4. 创建定时执行任务的线程池:java.ScheduledExecutorService executor =Executors.newScheduledThreadPool(3);这将创建一个定时执行任务的线程池,可以在给定的延迟之后或者周期性执行任务。
在使用完线程池后,需要调用`shutdown()`方法来关闭线程池: java.executor.shutdown();这将拒绝新任务的提交,等待已经提交的任务执行完成(包括等待队列中的任务),并且不接受新的任务。
以上是在Java 11中常见的线程池写法,通过选择合适的线程池类型,可以更好地满足不同场景下的需求。
java基础:简单实现线程池
java基础:简单实现线程池前段时间⾃⼰研究了下线程池的实现原理,通过⼀些源码对⽐,发现其实核⼼的东西不难,于是抽丝剥茧,决定⾃⼰实现⼀个简单线程池,当⾃已实现了出⼀个线程池后。
发现原来那么⾼⼤上的东西也可以这么简单。
先上原理图:为了更好的在⼿机上显⽰,我重新把图画了⼀遍上代码之前,要先补充⼀下线程池构造的核⼼⼏个点1. 线程池⾥的核⼼线程数与最⼤线程数2. 线程池⾥真正⼯作的线程worker3. 线程池⾥⽤来存取任务的队列BlockingQueue4. 线程中的任务task本例实现简化了⼀些,只实现了BlockingQueue存放任务,然后每个worker取任务并执⾏,下⾯看代码⾸先定义⼀个线程池ThreadExcutorclass ThreadExcutor{//创建private volatile boolean RUNNING = true;//所有任务都放队列中,让⼯作线程来消费private static BlockingQueue<Runnable> queue = null;private final HashSet<Worker> workers = new HashSet<Worker>();private final List<Thread> threadList = new ArrayList<Thread>();//⼯作线程数int poolSize = 0;//核⼼线程数(创建了多少个⼯作线程)int coreSize = 0;boolean shutdown = false;public ThreadExcutor(int poolSize){this.poolSize = poolSize;queue = new LinkedBlockingQueue<Runnable>(poolSize);}public void exec(Runnable runnable) {if (runnable == null) throw new NullPointerException();if(coreSize < poolSize){addThread(runnable);}else{//System.out.println("offer" + runnable.toString() + " " + queue.size());try {queue.put(runnable);} catch (InterruptedException e) {e.printStackTrace();}}}public void addThread(Runnable runnable){coreSize ++;Worker worker = new Worker(runnable);workers.add(worker);Thread t = new Thread(worker);threadList.add(t);try {t.start();}catch (Exception e){e.printStackTrace();}}public void shutdown() {RUNNING = false;if(!workers.isEmpty()){for (Worker worker : workers){worker.interruptIfIdle();}}shutdown = true;Thread.currentThread().interrupt();}//这⾥留个位置放内部类Worker}然后定义⼀个内部类Worker,这个内部类Worker是⽤来执⾏每个任务的,在创建线程池后,往线程⾥添加任务,每个任务都是由Worker⼀个⼀个来启动的。
线程池的使用实例
线程池的使用实例线程池是在多线程编程中非常实用的一种技术,它提供了一种优秀的解决方案来避免在创建大量线程时出现的一系列问题。
在现代计算机中,通常具有多核CPU,内存和缓存在核心之间共享,而这些核心共享的资源假定可以用来支持多个线程执行。
因此,线程池有助于利用这些多核心技术来实现并行执行,并可以管理所有可用线程以确保系统不会因执行多个线程而出现资源争用或系统崩溃等问题。
本文将以Java语言为例介绍线程池的外观,使用,并提供一些实践建议和注意事项。
1、实现线程池的Java类在Java中,线程池是通过java.util.concurrent.executor接口的一个实现来实现的,例如ThreadPoolExecutor类。
ThreadPoolExecutor是一个线程池的实现,它提供了配置线程池,调度和执行任务的方法。
它还提供了一个方便的方法来执行一个Runnable任务,并返回一个表示该任务成功完成的Future 对象。
下面的代码显示如何创建一个使用ThreadPoolExecutor的线程池:ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingQueue<>());其中,corePoolSize - 池中要保留的线程数,即使它们是空闲的的。
maximumPoolSize - 池可容纳的最大线程数。
keepAliveTime - 当线程数多于核心数时,多余的线程在终止之前保持空闲的时间量。
TimeUnit - 指定keepAliveTime的时间单位。
LinkedBlockingQueue - 用于在池里执行任务的队列,此处使用的LinkedBlockingQueue是一个无界队列,它按照FIFO(先进先出)的顺序插入元素,并且等待free thread来消耗队列中的任务。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
废话不多说开整
我用的是eclipse(这应该没多大影响)
建一个工程java工程和web工程都行然后建一个包建一个类带main方法
首先贴出来的是内部类
//继承了runnable接口
class MyTask implements Runnable {
private int taskNum;
public MyTask(int num) {
this.taskNum = num;
}
@Override
public void run() {
System.out.println("正在执行task "+taskNum);
try {
//写业务
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task "+taskNum+"执行完毕!");
}
}
接下来就是这个类
public class testOne {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 7, 10, LISECONDS, new ArrayBlockingQueue<Runnable>(2),new ThreadPoolExecutor.DiscardOldestPolicy() );
for(int i=0;i<15;i++){
MyTask myTask = new MyTask(i);
executor.execute(myTask);
System.out.println("线程池中线程数目:
"+executor.getPoolSize()+"队列等待执行的任务数目:"+
executor.getQueue().size()+"已经执行完别的任务数目:
"+executor.getCompletedTaskCount());
}
executor.shutdown();
}
}
接下来在说明一下ThreadPoolExecutor的参数设置ThreadPoolExecutor(int corePoolSize,//线程池维护线程的最少数量
int maximumPoolSize,//线程池维护线程的最大数量
long keepAliveTime,//线程池维护线程所允许的空闲时间
TimeUnit unit, 线程池维护线程所允许的空闲时间单位
BlockingQueue workQueue,线程池所使用的缓存队列
RejectedExecutionHandler handler线程池对拒绝任务的处理策略
)
handler有四个选择:
ThreadPoolExecutor.AbortPolicy()
抛出java.util.concurrent.RejectedExecutionException异常
ThreadPoolExecutor.CallerRunsPolicy()
重试添加当前的任务,他会自动重复调用execute()方法
ThreadPoolExecutor.DiscardOldestPolicy()
抛弃旧的任务
ThreadPoolExecutor.DiscardPolicy()
抛弃当前的任务
上面是一个例子接下来再来一个例子
建立一个类继承Runnable接口,大概是这样:
public class BelongTo2 implements Runnable {
@Override
public void run() {
try {
//当前线程休眠2秒当然也可以写业务
System.out.print("东西");
Thread.currentThread().sleep(2000);
System.out.print("\n");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
然后再
建立一个类带main方法,大概是这样:
public class Test2 {
public static void main(String[] args) {
//创建定长线程池大小为5
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
for(int i=0;i<20;i++){
BelongTo2 th=new BelongTo2();
fixedThreadPool.execute(th);
}
fixedThreadPool.shutdown();
}
}
运行就可以了。
简单介绍一下ExecutorService 这个类创建一个定长线程池,可控制线程最大并发数(后面的参数就是并发线程的数量),超出的线程会在队列中等待。