手把手教你做一个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语⾔本⾝也是多线程,回顾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实现手写一个简单版的线程池

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线程池的用法,包括线程池的创建、使用和销毁等方面。

一、线程池的创建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创建线程池的三种方法

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线程池的案例。

假设我们有一个需求,需要从一个文件夹中读取多个文件,并对每个文件进行处理。

由于文件的数量可能很大,为了提高处理速度,我们可以使用线程池来并发处理这些文件。

首先,我们需要创建一个线程池。

在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提供了线程池技术。

本文将介绍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之线程池简单实现线程池的技术背景在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。

在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。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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 这个类创建一个定长线程池,可控制线程最大并发数(后面的参数就是并发线程的数量),超出的线程会在队列中等待。

相关文档
最新文档