线程池概念

线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。

我们详细的解释一下为什么要使用线程池?(程序优化)

在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,创建和销毁线程花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务。

线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。

使用线程池方式--Runnable接口

通常,线程池都是通过线程池工厂创建,再调用线程池中的方法获取线程,再通过线程去执行任务方法。

l  Executors:线程池创建工厂类

n  public static ExecutorService newFixedThreadPool(int nThreads):返回线程池对象

l  ExecutorService:线程池类

n  Future<?> submit(Runnable task):获取线程池中的某一个线程对象,并执行

l  Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用

l  使用线程池中线程对象的步骤:

n  创建线程池对象

n  创建Runnable接口子类对象(创建任务)

n  提交Runnable接口子类对象(执行任务)

n  关闭线程池

代码演示:

public class ThreadPoolDemo {

public static void main(String[] args) {

//创建线程池对象

ExecutorService service = Executors.newFixedThreadPool(2);//包含2个线程对象

//创建Runnable实例对象

MyRunnable r = new MyRunnable();

//自己创建线程对象的方式

//Thread t = new Thread(r);

//t.start(); ---> 调用MyRunnable中的run()

//从线程池中获取线程对象,然后调用MyRunnable中的run()

service.submit(r);

//再获取个线程对象,调用MyRunnable中的run()

service.submit(r);

service.submit(r);

//注意:submit方法调用结束后,程序并不终止,是因为线程池控制了线程的关闭。将使用完的线程又归还到了线程池中

//关闭线程池

//service.shutdown();

}

}

l  Runnable接口实现类

public class MyRunnable implements Runnable {

@Override

public void run() {

System.out.println("我要一个教练");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("教练来了: " +Thread.currentThread().getName());

System.out.println("教我游泳,交完后,教练回到了游泳池");

}

}

使用线程池方式—Callable接口(专用于线程池)

l  Callable接口:与Runnable接口功能相似,用来指定线程的任务。其中的call()方法,用来返回线程任务执行完毕后的结果,call方法可抛出异常可设置返回值。

l  ExecutorService:线程池类

n  <T> Future<T> submit(Callable<T> task):获取线程池中的某一个线程对象,并执行线程中的call()方法

l  Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用

l  使用线程池中线程对象的步骤:

n  创建线程池对象

n  创建Callable接口子类对象

n  提交Callable接口子类对象

n  关闭线程池

代码演示:

public class ThreadPoolDemo {

public static void main(String[] args) {

//创建线程池对象

ExecutorService service = Executors.newFixedThreadPool(2);//包含2个线程对象

//创建Callable对象

MyCallable c = new MyCallable();

//从线程池中获取线程对象,然后调用MyRunnable中的run()

service.submit(c);

//再获取个教练

service.submit(c);

service.submit(c);

//注意:submit方法调用结束后,程序并不终止,是因为线程池控制了线程的关闭。将使用完的线程又归还到了线程池中

//关闭线程池

//service.shutdown();

}

}

l  Callable接口实现类,call方法可抛出异常、返回线程任务执行完毕后的结果

public class MyCallable implements Callable {

@Override

public Object call() throws Exception {

System.out.println("我要一个教练:call");

Thread.sleep(2000);

System.out.println("教练来了: " +Thread.currentThread().getName());

System.out.println("教我游泳,交完后,教练回到了游泳池");

return null;

}

}

线程池练习:返回两个数相加的结果

要求:通过线程池中的线程对象,使用Callable接口完成两个数求和操作

l  Future接口:用来记录线程任务执行完毕后产生的结果。

n  V get() 获取Future对象中封装的数据结果

代码演示:

public class ThreadPoolDemo {

public static void main(String[] args) throws InterruptedException, ExecutionException {

//创建线程池对象

ExecutorService threadPool = Executors.newFixedThreadPool(2);

//创建一个Callable接口子类对象

//MyCallable c = new MyCallable();

MyCallable c = new MyCallable(100, 200);

MyCallable c2 = new MyCallable(10, 20);

//获取线程池中的线程,调用Callable接口子类对象中的call()方法, 完成求和操作

//<Integer> Future<Integer> submit(Callable<Integer> task)

// Future 结果对象

Future<Integer> result = threadPool.submit(c);

//此 Future 的 get 方法所返回的结果类型

Integer sum = result.get();

System.out.println("sum=" + sum);

//再演示

result = threadPool.submit(c2);

sum = result.get();

System.out.println("sum=" + sum);

}

}

l  Callable接口实现类

public class MyCallable implements Callable<Integer> {

//成员变量

int x = 5;

int y = 3;

//构造方法

public MyCallable(){

}

public MyCallable(int x, int y){

this.x = x;

this.y = y;

}

@Override

public Integer call() throws Exception {

return x+y;

}

}

java ->多线程_线程池的更多相关文章

  1. Java多线程_线程池

    作用我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为 ...

  2. Java多线程与线程池技术

    一.序言 Java多线程编程线程池被广泛使用,甚至成为了标配. 线程池本质是池化技术的应用,和连接池类似,创建连接与关闭连接属于耗时操作,创建线程与销毁线程也属于重操作,为了提高效率,先提前创建好一批 ...

  3. Java 多线程:线程池

    Java 多线程:线程池 作者:Grey 原文地址: 博客园:Java 多线程:线程池 CSDN:Java 多线程:线程池 工作原理 线程池内部是通过队列结合线程实现的,当我们利用线程池执行任务时: ...

  4. java多线程、线程池及Spring配置线程池详解

    1.java中为什么要使用多线程使用多线程,可以把一些大任务分解成多个小任务来执行,多个小任务之间互不影像,同时进行,这样,充分利用了cpu资源.2.java中简单的实现多线程的方式 继承Thread ...

  5. Java多线程和线程池

    转自:http://blog.csdn.net/u013142781/article/details/51387749 1.为什么要使用线程池 在Java中,如果每个请求到达就创建一个新线程,开销是相 ...

  6. Java多线程之线程池详解

    前言 在认识线程池之前,我们需要使用线程就去创建一个线程,但是我们会发现有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因 ...

  7. JAVA多线程(三) 线程池和锁的深度化

    github演示代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-servic ...

  8. Java多线程-ThreadPool线程池(三)

    开完一趟车完整的过程是启动.行驶和停车,但老司机都知道,真正费油的不是行驶,而是长时间的怠速.频繁地踩刹车等动作.因为在速度切换的过程中,发送机要多做一些工作,当然就要多费一些油. 而一个Java线程 ...

  9. java 多线程 4 线程池

    系统启动一个新线程的成本是比较高的,因为它涉及到与操作系统的交互.在这种情况下,使用线程池可以很好的提供性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池. 与数据库连接池类似 ...

随机推荐

  1. Java中Character类

    Character 类在对象中包装一个基本类型char的值此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等),并将字符从大写转小写,反之亦然. 构造方法: Character(char ...

  2. SpringCloud-Alibaba-Nacos 服务注册中心&配置中心

    Spring Cloud Alibaba 由于 Spring Cloud Netflix 项目进入维护模式(将模块置于维护模式意味着 Spring Cloud 团队将不会再向模块中添加新功能,只会修复 ...

  3. Spring Boot Starters介绍

    文章目录 Web Start Test Starter Data JPA Starter Mail Starter 结论 对于任何一个复杂项目来说,依赖关系都是一个非常需要注意和消息的方面,虽然重要, ...

  4. Jdbc批处理一点异同

    同样的代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class TestBatch {   public stati ...

  5. 刷新DNS解析缓存+追踪+域名解析命令

    刷新DNS解析缓存 命令:ipconfig /flushdns 用于改完host之后. 追踪IP: 命令:tracert www.baidu.com 域名解析: 命令:nslookup www.bai ...

  6. SaltStack漏洞导致的挖矿排查思路

    描述 SaltStack是一套C/S架构的运维工具,服务端口默认为4505/4506,两个端口如果对外网开放危害非常大,黑客利用SaltStack的远程命令执行漏洞CVE-2020-11651可以直接 ...

  7. 70行实现Promise核心源码

    70行实现Promise核心源码 前言: ​ 一直以来都是只会调用Promise的API,而且调API还是调用axios封装好的Promise,太丢人了!!!没有真正的去了解过它的原理是如何实现的,自 ...

  8. Linux下swap到底有没有必要使用

    周五看到QQ群里在讨论Linux主机上到底需不需要开启swap空间,而且目前公有云主机默认都是把swap关了的,很多公司也是没有开启swap,那到底需不需要开启呢? 我之前在看<鸟哥的Linux ...

  9. 数据源管理 | 基于DataX组件,同步数据和源码分析

    本文源码:GitHub·点这里 || GitEE·点这里 一.DataX工具简介 1.设计理念 DataX是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDF ...

  10. python模块之time and datetime

    time # python3 # coding = utf-8 import time timestamp = time.time() print('timestamp:%s, type: %s' % ...