创建线程池



一、认识线程池

当前创建线程的问题

用户每发起一个请求,后台就需要创建一个新线程来处理,任务处理完毕之后,线程就会被销毁
下次新任务来了肯定又要创建新线程处理的,用完又要被销毁
而创建和销毁线程的开销是很大的,当请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能

什么是线程池?

线程池就是一个可以复用线程的技术
它就像一个大的池子一样,里面可以放置一些线程,当需要的时候,就从里面取出来用,用完了就还回去
如此一来,就不必频繁的创建和销毁线程了,大大的提高了线程的利用率,提供系统的性能

二、如何创建线程池?

线程池的执行流程

判断核心线程数是否已满,如果没满,则创建一个新的核心线程来执行任务
如果核心线程满了,则判断工作队列是否已满,如果没满,则将任务存储在这个工作队列
如果工作队列满了,则判断最大线程数是否已满,如果没满,则创建临时线程执行任务
如果最大线程数已满,则执行拒绝策略

如何得到线程池对象?

JDK 5.0起提供了代表线程池的接口:ExecutorService。
使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

参数一:corePoolSize : 指定线程池的核心线程的数量
参数二:maximumPoolSize:指定线程池的最大线程数量
参数三:keepAliveTime :指定临时线程的存活时间
参数四:unit:指定临时线程存活的时间单位(秒、分、时、天)
参数五:workQueue:指定线程池的任务队列
参数六:threadFactory:指定线程池的线程工厂
参数七:handler:指定线程池的任务拒绝策略(线程都在忙,任务队列也满了的时候,新任务来了该怎么处理)

任务缓冲队列参数:
ArrayBlockingQueue 基于数组的有界缓存等待队列,可以指定缓存队列的大小
LinkedBlockingQueue 基于链表的无界阻塞队列,此时最大线程数无效

任务拒绝策略参数:
ThreadPoolExecutor.AbortPolicy 丢弃任务并抛出RejectedExecutionException异常(默认策略)
ThreadPoolExecutor.DiscardPolicy 丢弃任务,但是不抛出异常 这是不推荐的做法
ThreadPoolExecutor.DiscardOldestPolicy 抛弃队列中等待最久的任务 然后把当前任务加入队列中
ThreadPoolExecutor.CallerRunsPolicy 由主线程负责调用任务的run()方法从而绕过线程池直接执行

三、线程池处理Runnable任务

ExecutorService的常用方法

void execute(Runnable command) 执行 Runnable 任务
Future submit(Callable task) 执行 Callable 任务,返回未来任务对象,用于获取线程返回的结果
void shutdown() 等全部任务执行完毕后,再关闭线程池!
List shutdownNow() 立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务

代码如下:

import java.util.concurrent.*;

/*
线程池执行Runnable任务
    void execute(Runnable command) 	执行Runnable任务
    void shutdown()  等全部任务执行完毕后,再关闭线程池!
    List<Runnable> shutdownNow() 立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务
*/
public class Demo2 {
    public static void main(String[] args) {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(5),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        poolExecutor.execute(new ARunnable());
        poolExecutor.execute(new ARunnable());
        poolExecutor.execute(new ARunnable());


        poolExecutor.execute(new ARunnable());
        poolExecutor.execute(new ARunnable());
        poolExecutor.execute(new ARunnable());
        poolExecutor.execute(new ARunnable());
        poolExecutor.execute(new ARunnable());


        poolExecutor.execute(new ARunnable());
        poolExecutor.execute(new ARunnable());


        poolExecutor.shutdown();
    }
}
class ARunnable implements Runnable{

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name+":线程执行了");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

四、线程池处理Callable任务

ExecutorService的常用方法

void execute(Runnable command) 执行任务/命令,没有返回值,一般用来执行 Runnable 任务
Future submit(Callable task) 执行任务,返回未来任务对象获取线程结果,一般拿来执行 Callable 任务
void shutdown() 等任务执行完毕后关闭线程池
List shutdownNow() 立刻关闭,停止正在执行的任务,并返回队列中未执行的任务

代码如下:


import java.util.concurrent.*;

/*
线程池执行Runnable任务
    Future<T> submit(Callable<T> task)	执行Callable任务,返回未来任务对象,用于获取线程返回的结果
    void shutdown()  等全部任务执行完毕后,再关闭线程池!
    List<Runnable> shutdownNow() 立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务
*/
public class Demo3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                3,
                5,
                10,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(5),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        SunCallable sunCallable = new SunCallable(5);
        Future<Integer> future = poolExecutor.submit(sunCallable);
        Integer integer = future.get();
        System.out.println(integer);
        poolExecutor.shutdown();
    }
}

//需求: 编写一个任务类, 可以通过构造器接收n, 计算并返回1~n的和
class SunCallable implements Callable<Integer>{
    private int num;

    public SunCallable(int num) {
        this.num = num;
    }

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i <= num; i++) {
            sum += i;
        }
        return sum;
    }
}
  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值