Java基础 第四节 第五课

举报
我是小白呀iamarookie 发表于 2021/09/11 02:04:05 2021/09/11
【摘要】 线程池 线程池思想概述线程池概念线程池的使用创建线程池创建对象的步骤代码实现 线程池思想概述 我们使用线程的时候去创建一个线程, 这样实现起来非常简便, 但是就会有一个问题: 如果并发...

线程池思想概述

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

那么有没有一种办法使得线程可以复用, 就是执行完一个任务, 并不被销毁, 而是可以继续执行其他任务>

在 Java 中可以通过线程池来达到这样的效果. 今天我们就来详细讲解一下 Java 的线程池.

线程池概念

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

由于线程池中有很多操作都是与优化资源相关的, 我们在这里就不多赘述. 我们通过一张图来了解线程池的工作原理:
在这里插入图片描述
合理利用线程池能够带来三个好处:

  1. 降低资源消耗. 减少了创建和销毁线程的次数, 每个工作线程都可以被重复利用, 可执行多个任务
  2. 提高响应速度. 当任务到达时, 任务可以不需要的等到线程创建就能立即执行
  3. 提高线程的可管理性. 可以根据系统的承受能力, 调整线程池中工作线线程的数目. 防止因为消耗过多的内存, 而把服务器累趴下. 每个线程需要大约 1MB 内存, 线程开的越多, 消耗的内存也就越大, 最后死机

线程池的使用

Java 里面线程池的顶级接口是java.util.concurrent.Executor, 但是严格意义上讲 Executor 并不是一个线程池, 而是一个执行线程的工具. 真正的线程池接口是java.util.concurrent.ExecutorService.

要配置一个线程池是比较复杂的, 尤其是对于线程池的原理不是很清楚的情况下, 很有可能配置的线程池不是较优的. 因此在java.util.concurrent.Executors线程工厂类里面提供了一些静态工厂, 生成一些常用的线程池. 官方讲义使用 Executors 工程类来创建线程池对象.

创建线程池

Executors 类中有个创建线程池的方法如下:

public static ExecutorService newFixedThreadPool(int nThreads): 
返回线程池对象. (创建的是有界限的线程池, 
也就是线程池中的线程个数可以指定最大数量)

  
 
  • 1
  • 2
  • 3

获取到了一个线程池 ExecutorService 对象, 那么怎么使用呢? 这里定义了一个使用线程池对象的方法如下:

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

  
 
  • 1
  • 2

创建对象的步骤

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

  1. 创建线程池对象
  2. 创建 Runnable 接口子类对象 (task)
  3. 提交 Runnable 接口子类对象 (take task)
  4. 关闭线程池 (一般不做)

代码实现

Runnable 实现类代码:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("我要一个教练!");
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("马保国来了: " + Thread.currentThread().getName());
        System.out.println("教了我一套闪电五连鞭, 然后被英国大力士打死了.");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

线程测试类:

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

public class Test {
    public static void main(String[] args) {
        // 创建线程池对象
        ExecutorService executorService = Executors.newFixedThreadPool(2);  // 包含2个线程对象
        // 创建Runnable实例对象
        MyRunnable r = new MyRunnable();

        // 自己创建线程对象的方式
        Thread t = new Thread(r);
        t.start();

        // 从线程池中获取线程对象, 然后调用MyRunnable中的run()
        executorService.submit(r);
        executorService.submit(r);
        // 注意: submit方法调用结束后, 程序并不终止, 是因为线程池控制了线程的关闭。
        // 将使用完的线程又归还到了线程池中
        
        // 关闭线程池
        executorService.shutdown();
    }
}

输出结果:
我要一个教练!
我要一个教练!
我要一个教练!
马保国来了: Thread-0
教了我一套闪电五连鞭, 然后被英国大力士打死了.
马保国来了: pool-1-thread-1
教了我一套闪电五连鞭, 然后被英国大力士打死了.
马保国来了: pool-1-thread-2
教了我一套闪电五连鞭, 然后被英国大力士打死了.

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

文章来源: iamarookie.blog.csdn.net,作者:我是小白呀,版权归原作者所有,如需转载,请联系作者。

原文链接:iamarookie.blog.csdn.net/article/details/111503743

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。