其他一些收藏

Java--线程池

2021-10-15  本文已影响0人  aruba
Java中提供了一系列和锁相关的工具:synchronized、ReentrantLock、AtomicXXX类,它们都能帮助解决我们进行多线程操作时并发问题,之前我们也提到了内核线程模型,Hotspot虚拟机线程的创建都是通过内核线程提供的轻量级进程API创建的,反复的创建线程会不断的由OS线程调度,这也会消耗大量CPU性能
争对创建线程,除了使用Thread之外,Java还提供了线程池类,它们最终都实现的Executor接口,JDK1.7中的继承实现关系如下:

一、使用线程池与Thread对比

使用Thread创建10000个线程,并运行,记录时间:

public class ThreadPoolTest {

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        List<Thread> threads = new ArrayList<>(10000);

        for (int i = 0; i < 10000; i++) {
            Thread thread = new Thread();
            threads.add(thread);
            thread.start();
        }

        for(Thread t:threads){
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("ms:"+(System.currentTimeMillis() - startTime));
    }

}

结果:
ms:1761

使用线程池:

public class ThreadPoolTest2 {

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        int size = 10000;

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        final CountDownLatch countDownLatch = new CountDownLatch(size);

        for (int i = 0; i < size; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    countDownLatch.countDown();
                }
            });
        }

        try {
            countDownLatch.await();//等待10000计数结束
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executorService.shutdown();
        System.out.println("ms:" + (System.currentTimeMillis() - startTime));
    }

}

结果:
ms:69

两者相差的时间为100倍以上,这边使用的线程池回头再来看,由这个例子可以看出,线程的创建到运行过程,会花费大量的cpu时间,争对需要大量并发的操作,使用线程池可以大大提高程序性能

二、ThreadPoolExecutor

1.ThreadPoolExecutor执行任务图解

Executors是个帮助类,内部实际使用的是ThreadPoolExecutor,构造函数如下:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

ThreadPoolExecutor大致的执行场景如下:


execute方法执行流程
2.ThreadPoolExecutor参数

再来看构造函数中各个参数的含义:

3.任务队列

任务队列实现BlockingQueue接口,JDK提供了以下4种:

4.拒绝策略

三、Executors

后台一般不允许使用Executors,但我们安卓开发是可以使用的,接下来来使用Executors三种线程池,有了上面ThreadPoolExecutor的了解,理解起来很简单

public class ThreadPoolTest3 {

    public static void main(String[] args) {
        ExecutorService executorService1 = Executors.newCachedThreadPool();
        ExecutorService executorService2 = Executors.newFixedThreadPool(10);
        ExecutorService executorService3 = Executors.newSingleThreadExecutor();
        for (int i = 1; i <= 100; i++) {
            executorService1.execute(new TestRunnable(i));
//            executorService2.execute(new TestRunnable(i));
//            executorService3.execute(new TestRunnable(i));
        }
    }

    static class TestRunnable implements Runnable {
        int i = 0;

        public TestRunnable(int i) {
            this.i = i;
        }


        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + ":" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
1.newCachedThreadPool

newCachedThreadPool方法如下:

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

它和直接创建线程类似,可以创建无限的线程

2.newFixedThreadPool

newFixedThreadPool方法如下:

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

它拥有指定大小的核心线程数,并且只有核心线程,以及一个无限大小的任务队列

3.newSingleThreadExecutor

newSingleThreadExecutor方法如下:

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

它仅有一个核心线程,以及一个无限大小的任务队列,所以相当于单线程执行任务队列中的任务

上一篇下一篇

猜你喜欢

热点阅读