ExecutorService线程池详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qiaziliping/article/details/79881806
  • 对线程池 “池”的理解
    可以理解为工厂,如果工厂生产斧头,小王从工厂借了一把,当小王用完了,还给工厂,之后小李也可以借去用
    复用已有资源
    控制资源总量

你一个任务过来了,我发现池子里有没事干并且还活着的线程,来,拿去用,我也不用费事给你创建一条线程了,要知道线程的创建和销毁可都是麻烦事
你一个任务过来了,我发现池子的线程都在忙,并且现在池子的线程已经太多了,在不限制下去就要内存溢出了,来,排队去

线程池的作用

1、new Thread的弊端

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("--------");
    }
}).start();

a. 每次new Thread新建对象性能差:每次都要经历新建,就绪,运行,阻塞,死亡
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。

2、相比new Thread,Java提供的四种线程池的好处在于:
a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。

Executors介绍

通过Executors可以获得四种线程池
Executors
ExecutorService service = Executors.newCachedThreadPool();
//创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。池中物任务时,超过60秒,会自动关闭线程池。

ExecutorService service = Executors.newSingleThreadExecutor();
// 单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。(测试时都是先进先出的规则)

ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
//创建一个定长线程池,支持定时及周期性任务执行。ScheduledExecutorService为ExecutorService的子类

ExecutorService service = Executors.newFixedThreadPool(15);
//创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

例子

  • 线程TestThread
public class TestThread extends Thread{

    @Override
    public void run() {
        try {
            Thread.sleep(1000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(System.currentTimeMillis()+"===="+ getPriority()+"----数据库操作---"+this.getName());
    }
}
  • 缓存线程池Executors.newCachedThreadPool();
ExecutorService service = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
    Thread td = new TestThread();
    service.execute(td);
}
  • 单例线程池Executors.newSingleThreadExecutor();
ExecutorService service = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
    Thread td = new TestThread();
    service.execute(td);
}
// 打印结果
// 1523331778779====5----数据库操作---Thread-0
// 1523331779780====5----数据库操作---Thread-1
// 1523331780780====5----数据库操作---Thread-2
// 1523331781780====5----数据库操作---Thread-3
// 1523331782780====5----数据库操作---Thread-4
// 1523331783780====5----数据库操作---Thread-5
// 1523331784780====5----数据库操作---Thread-6
// 1523331785780====5----数据库操作---Thread-7
// 1523331786781====5----数据库操作---Thread-8
// 1523331787781====5----数据库操作---Thread-9
  • 定时线程池Executors.newScheduledThreadPool(10);
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
for (int i = 0; i < 10; i++) {
    Thread td = new TestThread();
    service.schedule(td, 5, TimeUnit.SECONDS); // 添加任务5秒之后执行
}
  • 定长线程池Executors.newFixedThreadPool(15);
ExecutorService service = Executors.newFixedThreadPool(15);
for (int i = 0; i < 10; i++) {
    Thread td = new TestThread();
    service.execute(td);
}

项目中的用法

package com.hesvit.common.task.execute;

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

/**
 * <p>
 * 线程池创建
 * <p>
 * @author liuping
 * @since 2017年12月26日
 */
public class TaskExecute {
    // 创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
    private static ExecutorService fixedThreadPool; 
    // 创建固定容量大小的缓冲池
    private static ExecutorService singleThreadExecutor;
    // 创建容量为1的缓冲池
    private static ExecutorService cachedThreadPool; 

    public static ExecutorService newFixedThreadPool(int nThreads) {
        if (fixedThreadPool == null)
            return Executors.newFixedThreadPool(nThreads);
        else
            return fixedThreadPool;
    }

    public static ExecutorService newSingleThreadExecutor() {
        if (singleThreadExecutor == null)
            return Executors.newSingleThreadExecutor();
        else
            return singleThreadExecutor;
    }

    public static ExecutorService newCachedThreadPool() {
        if (cachedThreadPool == null)
            return Executors.newCachedThreadPool();
        else
            return cachedThreadPool;
    }

    public static void execute(Runnable task) {
        newFixedThreadPool(6).execute(task);
    }
}

TaskExecute.execute(new RefreshAppUserThread());// 刷新app用户信息

// 线程
public class RefreshAppUserThread extends Thread {

    @Override
    public void run() {
        RedisUtil.refreshAppUser();
    }

}


import redis.clients.jedis.Jedis;
@Component
public class RedisUtil {

    /** 过时时间为2小时:2 * 60 *60 */
    private static int EXPIRE_2_HOUR = 7200;
    // 缓存所有App用户
    private static String ALL_APP_USERS = "all_app_users";


    public static List<User> refreshAppUser() {
        return refreshAppUser(null);
    }

    /**
     * 刷新App用户列表
     * liuping
     */
    public static List<User> refreshAppUser(Jedis redis) {
        if (redis == null)
            redis = MyJedisPool.getJedisObject();// 获得jedis实例
        List<User> users = new ArrayList<>();
        try {
            User user = new User();
            user.setLimit(-1);
            WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
            UserService service = (UserService) context.getBean("userService");

            users = service.selectByIndex(user);

            if (null != users) {
                JSONArray jsonArray = JSONArray.fromObject(users);
                String struser = String.valueOf(jsonArray);
                redis.set(ALL_APP_USERS, struser);
                redis.expire(ALL_APP_USERS, EXPIRE_2_HOUR); // 设置过期时间
            }
        } catch (Exception e) {
            logger.error("Failed to get wxuser from redis: {}", e.getMessage());
        } finally {
            MyJedisPool.recycleJedisOjbect(redis);
        }
        return users;
    }

}

猜你喜欢

转载自blog.csdn.net/qiaziliping/article/details/79881806