为什么需要线程池
java中为了提高并发度,可以使用多线程共同执行,但是如果有大量线程短时间之内被创建和销毁,会占用大量的系统时间,影响系统效率。
为了解决上面的问题,java中引入了线程池,可以使创建好的线程在指定的时间内由系统统一管理,而不是在执行时创建,执行后就销毁,从而避免了频繁创建、销毁线程带来的系统开销。
创建线程池的方式
创建线程池的方式有 7 种:
1.newFixedThreadPool
创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。
代码示例如下:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExecutorTest extends Thread { private int index; public MyExecutor(int i) { this.index = i; } public void run() { try { System.out.println("[" + this.index + "] start...."); Thread.sleep((int) (Math.random() * 10000)); System.out.println("[" + this.index + "] end."); } catch (Exception e) { e.printStackTrace(); } } public static void main(String args[]) { ExecutorService service = Executors.newFixedThreadPool(4); for (int i = 0; i < 10; i++) { service.execute(new MyExecutor(i)); // service.submit(new MyExecutor(i)); } System.out.println("submit finish"); service.shutdown(); } }
2.newCachedThreadPool
创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。
代码示例如下:
public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { final int j=i; executorService.submit(()->{ try { TimeUnit.MILLISECONDS.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" "+j); }); } System.out.println(executorService); }
3.newSingleThreadExecutor
创建单个线程数的线程池,它可以保证先进先出的执行顺序。
代码示例如下:
public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 6; i++) { final int j=i; executorService.execute(()->{ System.out.println(Thread.currentThread().getName()+" "+j); }); } executorService.shutdown(); }
4.newScheduledThreadPool
创建一个可以执行延迟任务的线程池,延迟执行。
代码示例如下:
public static void main(String[] args) { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(int corePoolSize); scheduledExecutorService.schedule(new Runnable() { @Override public void run() { log.warn("schedule run"); } }, 3, TimeUnit.SECONDS); }
5.newSingleThreadScheduledExecutor
创建一个单线程的可以执行延迟任务的线程池。
代码示例如下:
public static void main(String[] args) throws Exception { ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); // 1秒打印一次 当前线程名 service.scheduleAtFixedRate(() -> System.out.println(Thread.currentThread().getName()), 1, 1, TimeUnit.SECONDS); // 主线程等待10秒 TimeUnit.SECONDS.sleep(10); System.out.println("主线程退出了"); }
输出:
pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 主程序退出了 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1
6.newWorkStealingPool
创建一个抢占式执行的线程池(任务执行顺序不确定)【JDK 1.8 添加】。
代码示例如下:
public static void main(final String[] arguments) throws InterruptedException { ExecutorService excr = Executors.newWorkStealingPool(); ThreadPoolExecutor mypool = (ThreadPoolExecutor) Executors.newCachedThreadPool();; System.out.println("size of mypool:" + mypool.getPoolSize()); excr.submit(new Threadimpl()); excr.submit(new Threadimpl()); System.out.println("Total number threads scheduled):"+ mypool.getTaskCount()); excr.shutdown(); } static class Threadimpl implements Runnable { public void run() { try { Long num = (long) (Math.random() / 30); System.out.println("Thread Name:" +Thread.currentThread().getName()); TimeUnit.SECONDS.sleep(num); System.out.println("after sleep Thread Name:" +Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } }
7.ThreadPoolExecutor
最原始的创建线程池的方式,它包含了 7 个参数可供设置。
代码示例如下:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ThreadPoolExecutorDemo { private static final int CORE_POOL_SIZE = 5; private static final int MAX_POOL_SIZE = 10; private static final int QUEUE_CAPACITY = 100; private static final Long KEEP_ALIVE_TIME = 1L; public static void main(String[] args) { //使用阿里巴巴推荐的创建线程池的方式 //通过ThreadPoolExecutor构造函数自定义参数创建 ThreadPoolExecutor executor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<>(QUEUE_CAPACITY), new ThreadPoolExecutor.CallerRunsPolicy()); for (int i = 0; i < 10; i++) { //创建WorkerThread对象(WorkerThread类实现了Runnable 接口) Runnable worker = new MyRunnable("" + i); //执行Runnable executor.execute(worker); } //终止线程池 executor.shutdown(); while (!executor.isTerminated()) { } System.out.println("Finished all threads"); } }
mikechen睿哥
mikechen睿哥,十余年BAT架构经验,资深技术专家,就职于阿里、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》