JAVA线程池简单理解

什么是线程池

线程池的基本思想是一种对象池,在程序启动时候就开辟一块内存空间,里面存放众多的(未死亡)的线程。池中线程执行调度由线程池管理器来处理。当有线程任务是,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源

两种线程模型

a. 用户级线程(ULK)
由应用本身管理,不依赖操作系统核心,不需要用户态/核心态切换
那么什么是内核态,什么是用户态呢?只要想一想现实生活中,处于社会核心的人与处于社会边缘的人有什么区别就能明白处于核心的人拥有的资源多!因此,内核态就是拥有资源多的状态,或者说访问资源多的状态,我们也称之为特权态,速度块。相对来说,用户态就是非特权态,在此种状态下访问的资源将受到限制。
在这里插入图片描述

b. 内核级线程(KLT)在JVM用的99%线程属于KLT,CPU管理,依赖操作系统
在这里插入图片描述
两种权限,用户访问用户空间,内核空间只能内核访问,JVM虽然安装在用户空间,但可以调用系统开放的API,创建线程,映射到底层内核线程,所以JVM的线程要切换用户态于内核态,Java依赖于内核线程,为了避免资源过度消耗重要中线用户线程。

优势

线程池的使用:

  1. 单个任务处理的时间比较短
  2. 需要处理的任务数量很大
    优势:
    a. 重要线程,减少线程创建,消亡的开销,提高性能
    b. 提高响应速度
    c. 提高线程的可管理性
    d. 运用线程池能有效的控制线程最大并发数,可以根据系统的承受能力,调整线程池的线程数目,也就能防止消耗过多的内存,减少宕机几率。
    f. 对线程进行一些简单的管理,比如:延时执行,定时循环执行的策略等。

Executor框架是一种将线程的创建和执行分离的机制。它基于Executor和ExecutorService接口,及这两个接口的实现类ThreadPoolExecutor展开,Executor有一个内部线程池,并提供了将任务传递到池中线程以获得执行的方法,可传递的任务有如下两种:通过Runnable接口实现的任务和通过Callable接口实现的任务。在这两种情况下,只需要传递任务到执行器,执行器即可使用线程池中的线程或新创建的线程来执行任务。执行器也决定了任务执行时间。

Java提供了四种线程池的实现:

(1)newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

  public static void main(String[] args) {
        ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cacheThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "  " + index);
                }
            });
        }
    }

线程池为无限大,当执行当前任务时上一个任务已经完成,会复用执行上一个任务的线程,而不用每次新建线程
(2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

 public static void main(String[] args) {
        ExecutorService cacheThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int index = i;
            cacheThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "  " + index);
                }
            });
        }
    }

因为线程池大小为3,每个任务输出打印结果后sleep 2秒,所以每两秒打印3个结果。
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()

(3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

public static void main(String[] args) {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
             //延迟1秒后每3秒执行一次
           scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            public void run() {
                          System.out.println("延迟1秒后每3秒执行一次");
            }

      }, 1, 3, TimeUnit.SECONDS);
    }

(4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

 public static void main(String[] args) {
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            singleThreadExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    //结果依次输出,相当于顺序执行各个任务
                    System.out.println(Thread.currentThread().getName() + "  " + index);
                }
            });
        }
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值