线程创建之线程池

29 篇文章 0 订阅

多线程系列文章

Thread类及常见方法

线程的状态

线程安全问题

多线程案例



线程池

什么是线程池

所谓线程池,其实可以理解为是一个存放线程的池子,我们首先创建线程到线程池中,在需要用到该线程时,再从线程池中取出相应的线程进行加载,使用完毕以后,再归还线程到线程池中;但实际上,线程池更加倾向于是一种解决问题的思想,而并非在内存中有一块线程池的空间;


为什么要引入线程池

还记得在进程部分,我们谈到明明进程就可以实现并发编程,为何又要引入线程呢?
我们说,进程本身是相当重量的,创建进程需要申请资源,销毁进程需要释放资源,在频繁的进程创建销毁的过程中,成本是极高的,因此我们引入了线程;
线程通过对同一组资源的共用,在一定程度对进程的成本问题做出了优化,但是仅仅这样的优化是不够的,线程进行频繁的创建和销毁同样带来了问题;因此我们引入了线程池的概念,创建线程到线程池,使用完毕以后归还线程到线程池,不再通过系统来创建和销毁,由于从线程池中的操作属于纯用户态操作,而通过系统创建的操作属于内核态操作,因此可以有效提高效率。


java中的线程池

java中提供了一个静态工厂来创建不同的线程池,即Executors工厂类;

public class Demo1 {
    public static void main(String[] args) {
        //创建出固定包含10个线程的线程池
        ExecutorService threadPool= Executors.newFixedThreadPool(10);
        //返回值类型:ExecutorService
        for (int i=0;i<100;i++){
            //注册任务到线程池中
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello threadPool");
                }
            });
        }
    }
}

Executors类中提供了多种创建线程池的方式,上面代码演示的是创建固定线程数的线程池,还有线程数目动态增长的线程池的创建(newCachedThreadPool:)、只包含单个线程的线程池的创建(newSingleThreadExecutor)等,可以在不同的应用场景中自发选择,这里不做过多描述;


模拟实现一个线程池

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;


//创建一个线程池类
class MyThreadPool{
    //以阻塞队列来存放要完成的任务
    private BlockingQueue<Runnable> queue=new LinkedBlockingQueue<>();
    //往线程池中插入任务
    public void submit(Runnable runnable){
        try {
            //把线程放入队列
            queue.put(runnable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //设置线程池中的线程个数 n
    public MyThreadPool(int n){
        //创建线程来完成执行任务的工作
        for (int i=0;i<n;i++){
            Thread t=new Thread(()->{
                while (!Thread.currentThread().isInterrupted()){
                    try {
                        //从队列取出线程来执行
                        Runnable runnable=queue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        MyThreadPool myThreadPool=new MyThreadPool(10);
        for (int i=0;i<100;i++){
            myThreadPool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("MyThreadPool");
                }
            });
        }
    }
}

这里模拟实现的是一个固定了线程数的线程池,这种线程池的特点是:

如果线程数没有达到线程池的固定数量,每提交一个任务,线程池内就创建一个新线程,直到线程达到线程池的固定数量;当线程池的大小达到了固定数量时,就会保持不变,直到有线程因为执行异常而结束,线程池中就会补充一个新的线程;
一般这样一种线程池适用于处理CPU密集型的任务;


使用线程池,可以有效降低Java线程的创建成本,线程主要解决了以下2个问题:

线程池带来的好处

  • 提升性能:线程池可以独立负责线程的创建、维护及分配,将任务交给线程池去调度,线程池会尽可能使用空闲的线程去执行任务,对已经创建的线程进行复用,明显提升性能;
  • 线程管理:每个Java线程池都会对线程的一些基本信息进行统计,像完成的任务数量或空闲时间等,可以对线程进行有效的管理,从而实现对任务的高效调度;

在许多企业的编程规范中,线程必须通过线程池提供,为了减少系统资源的开销,由此也见线程池的优越。


over!

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值