【线程池、有返回值的线程池、线程池监控】

什么是线程池?

就是提前创建好了几个线程给他放到一个容器里,有任务需要执行时,出来一个线程执行任务,任务执行完了不销毁线程,然后放回去,等待下一次任务到来。

线程池的好处

  1. 降低创建线程和销毁线程的性能开销
  2. 提高响应速度,当有新任务需要执行是不需要等待线程创建就
    可以立马执行
  3. 合理的设置线程池大小可以避免因为线程数超过硬件资源瓶颈
    带来的问题

Java提供的四种线程池

1、newCachedThreadPool:用来创建一个可以无限扩大的线程池,适用于负载较轻的场景,执行短期
异步任务。(可以使得任务快速得到执行,因为任务时间执行短,可以很快结束,也不会造成cpu过度
切换)
2、newFixedThreadPool:创建一个固定大小的线程池
3、newSingleThreadExecutor:创建一个单线程的线程池,适用于需要保证顺序执行各个任务。
4、newScheduledThreadPool:适用于执行延时或者周期性任务。

newFixedThreadPool:
固定大小的线程池,每次有任务就创建一个线程,直到线程达到线程池的最大值,后面的任务会放到一个队列里,等待线程空闲的时候执行

public class PoolDemo implements Runnable{
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        for (int i = 0; i <100 ; i++) {
            pool.execute(new PoolDemo() {
            });

        }
        pool.shutdown();

    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

代码结果
newFixedThreadPool
可以很清楚看见只有3个线程在运行,这就是线程池的好处,循环利用已有的线程。

newSingleThreadExecutor:
java线程池中单一的线程池。表示是一个线程池,可以添加多个子线程,但是只有一个线程能运行,当前线程执行完了后下一个添加进来的线程才能运行。单一的线程池,该线程池中每时每刻只有一个线程能运行。添加进入的线程必须等待当前执行的线程执行完了后,才能执行(依照先进先出)

public class PoolDemo implements Runnable{
    public static void main(String[] args) {
        ExecutorService pool = Executors.newSingleThreadExecutor();
        for (int i = 0; i <100 ; i++) {
            pool.execute(new PoolDemo() {
            });
        }
        pool.shutdown();

    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

newSingleThreadExecutor
这个就是只有一个线程。

newCachedThreadPool:
动态伸缩线程池,任务到来,回收空闲的线程,若没有空闲的,则新建

public class PoolDemo implements Runnable{
    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();
        for (int i = 0; i <100 ; i++) {
            pool.execute(new PoolDemo() {
            });
        }
        pool.shutdown();

    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

newCachedThreadPool
newScheduledThreadPool:
周期性线程池

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

        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
        scheduledThreadPool.schedule(new Runnable() {
            @Override
            public void run() {
                // 延迟3秒执行
                System.out.println("延迟3秒执行,当前线程:" + Thread.currentThread().getName() + "当前任务时间:"
                        + DateFormat.getTimeInstance().format(new Date()));
            }
        }, 3, TimeUnit.SECONDS);
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                // 延迟1秒,每隔3秒执行
                System.out.println("延迟1秒,每隔3秒执行,当前线程:" + Thread.currentThread().getName() + "当前任务时间:"
                        +DateFormat.getTimeInstance().format(new Date()));
            }
        }, 1, 3, TimeUnit.SECONDS);
    }
}

newScheduledThreadPool

如果大家查看源码会发现,前三个里面其实都是new ThreadPoolExecutor

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

区别只是这个ThreadPoolExecutor后面参数不一样而已

   ThreadPoolExecutor(int corePoolSize,//核心线程数
             int maximumPoolSize,//最大线程数
             long keepAliveTime,//线程存活时间
             TimeUnit unit,
             BlockingQueue<Runnable> workQueue,//任务队列
             ThreadFactory threadFactory,//线程创建工厂
             RejectedExecutionHandler handler) //饱和策略

有返回值的线程池

public class CallableFutureDemo implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("hello");
        Thread.sleep(3000);
        return "你好";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        CallableFutureDemo callableFutureDemo = new CallableFutureDemo();
        FutureTask futureTask  = (FutureTask)executorService.submit(callableFutureDemo);
        System.out.println(futureTask.get());
    }
}

线程池监控

自己新建一个Exectors ,然后去把源码复制一个

public class Exectors {
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolSelf(nThreads, nThreads,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
    }
}

然后新建一个ThreadPoolSelf继承ThreadPoolExecutor,重写shutdown,beforeExecute,afterExecute。

public class ThreadPoolSelf extends ThreadPoolExecutor {
    public ThreadPoolSelf(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    @Override
    public void shutdown() {
        super.shutdown();
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        System.out.println(Thread.currentThread().getName()+"线程开始时间:"+ DateFormat.getTimeInstance().format(new Date()));
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        System.out.println("初始线程数:"+this.getPoolSize());
        System.out.println("核心线程数:"+this.getCorePoolSize());
        System.out.println("正在执行的任务数量:"+this.getActiveCount());
        System.out.println("已经执行的任务数量:"+this.getCompletedTaskCount());
        System.out.println("任务总数:"+this.getTaskCount());
    }
}

然后就可以把我们需要的信息打印出来了。

public class PoolDemo implements Runnable{
    public static void main(String[] args) {
        ThreadPoolExecutor pool = (ThreadPoolExecutor) Exectors.newFixedThreadPool(3);
        //可以提前预热所有核心线程
        pool.prestartAllCoreThreads();
        for (int i = 0; i <100 ; i++) {
            pool.execute(new PoolDemo() {
            });
        }
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值