• java预定义的四种线程池
  1. SingleThreadExexcutor:单线程数的线程池
  2. FixedThreadPool:固定线程数的线程池
  3. CacheThreadPool:可缓存的线程池
  4. ScheduledThreadPoo:支持定时或周期任务的线程池

这四种线程池都有各自问题,建议自定义线程池类(继承ThreadPoolExecutor),使用自定义的线程池,这样能对各个线程池参数都熟悉,避免使用过程中出错

  • 四种线程池源码

上面四种线程池类都继承ThreadPoolExecutor,在创建时都是直接返回new ThreadPoolExecutor(参数),不同的是定义的ThreadPoolExecutor(参数)中参数不同,而ThreadPoolExecutor又继承ExecutorService类

(1)FixedThreadPool

使用线程池有何注意事项呢?_线程池

(2)CacheThreadPool

 使用线程池有何注意事项呢?_线程池_02

(3)SingleThreadExecutor


使用线程池有何注意事项呢?_线程池_03

上面代码神似new FixedThreadPoop(1),但又有区别,因为外面多了一层FinalizableDelegatedExecutorService,其作用如下:

使用线程池有何注意事项呢?_线程池_04

可知,FixedThreadPoop可以向下转换,然后重新对其线程池进行配置参数【派变=(强转)基变,派变的范围大,向下转换即转为范围大的对象,简称“吓大”】,但SingleThreadExecutor不可以向下转换,故SingleThreadExecutor被创建后,无法再修改其线程池参数,真正地做到single单个线程。

(4)ScheduledThreadPool

public static ScheduledExecutorService new ScheduledThreadPool(int corePoolSize) 
{   return new ScheduledThreadPoolExecutor(corePoolSize);
}

其中ScheduledThreadPoolExecutor继承了ThreadPoolExecutor,故new ScheduledThreadPoolExecutor(corePoolSize)还是返回了父类构造new ThreadPoolExecutor();


  • 自定义线程池
  1. ThreadPoolExecutor构造方法

  使用线程池有何注意事项呢?_线程池_05

 其参数解释:


使用线程池有何注意事项呢?_线程池_06

  1. 自定义线程池

使用了有界队列,并自定义线程创建工厂ThreadFactory和拒绝策略handler


public class ThreadTest {public static void main(String[] args) throws InterruptedException, IOException {int corePoolSize = 2;int maximumPoolSize = 4;long keepAliveTime = 10;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        ThreadFactory threadFactory = new NameTreadFactory();
        RejectedExecutionHandler handler = new MyIgnorePolicy();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
                workQueue, threadFactory, handler);
        executor.prestartAllCoreThreads(); // 预启动所有核心线程        for (int i = 1; i <= 10; i++) {
            MyTask task = new MyTask(String.valueOf(i));
            executor.execute(task);
        }
        System.in.read(); //阻塞主线程    }static class NameTreadFactory implements ThreadFactory {private final AtomicInteger mThreadNum = new AtomicInteger(1);
        @Overridepublic Thread newThread(Runnable r) {
            Thread t = new Thread(r, "my-thread-" + mThreadNum.getAndIncrement());
            System.out.println(t.getName() + " has been created");return t;
        }
    }public static class MyIgnorePolicy implements RejectedExecutionHandler {public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            doLog(r, e);
        }private void doLog(Runnable r, ThreadPoolExecutor e) {// 可做日志记录等System.err.println( r.toString() + " rejected");//          System.out.println("completedTaskCount: " + e.getCompletedTaskCount());        }
    }static class MyTask implements Runnable {private String name;public MyTask(String name) {this.name = name;
        }
        @Overridepublic void run() {try {
                System.out.println(this.toString() + " is running!");
                Thread.sleep(3000); //让任务执行慢点} catch (InterruptedException e) {
                e.printStackTrace();
            }
        }public String getName() {return name;
        }
        @Overridepublic String toString() {return "MyTask [name=" + name + "]";
        }
    }
}

运行结果:

  使用线程池有何注意事项呢?_线程池_07

其中7-10号线程被拒绝策略拒绝了,1、2号线程执行完后,3、6号线程进入核心线程池执行,此时4、5号线程在任务队列等待执行,3、6线程执行完再通知4、5线程执行

 

文章定期同步更新于公众号【小大白日志】,欢迎关注公众号:

使用线程池有何注意事项呢?_线程池_08