Java|Java线程池介绍与基本案例

Java线程池 线程池的概念:首先创建一些线程,他们的集合成为线程池,当服务器接收到一个客户请求后,就从线程池中取出一个空闲的线程为之服务,服务完后不关闭该线程,而是将线程还到线程池中。
线程池的两个主要作用:
控制线程数量(避免因为创建大量的线程导致的系统崩溃)
重用线程(避免频繁地创建销毁线程)
1.
Callable 内有个 call方法可以有返回值 Runnable run方法无返回值
ExecutorService 接口继承与Executor submit方法独有返回Future
Executors 操作Executor工具类
2. ThreadPool (Executors.newFixedThreadPool(5))

public class T05_ThreadPool { public static void main(String[] args) throws InterruptedException { //创建固定大小的线程池 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); for (int i = 0; i <= 5; i++){ fixedThreadPool.execute(() -> {try {TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {e.printStackTrace(); } System.out.println("当前运行的线程:"+ Thread.currentThread().getName()); }); } System.out.println(fixedThreadPool); fixedThreadPool.shutdown(); System.out.println(fixedThreadPool.isTerminated()); System.out.println(fixedThreadPool.isShutdown()); TimeUnit.SECONDS.sleep(5); System.out.println(fixedThreadPool.isTerminated()); System.out.println(fixedThreadPool.isShutdown()); System.out.println(fixedThreadPool); }}

【Java|Java线程池介绍与基本案例】3. FutureTaskPool
public class T06_FutureTaskPool { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask futureTask = new FutureTask(() -> { TimeUnit.MILLISECONDS.sleep(500); return 10086; }); //内部是Callable中call方法 new Thread(futureTask).start(); //启动线程 System.out.println(futureTask.get()); //该方法是一个阻塞方法 执行结束该线程才完成 System.out.println("***************************************"); //创建线程池 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); Future submit = fixedThreadPool.submit(() -> { TimeUnit.MILLISECONDS.sleep(500); return 10010; }); fixedThreadPool.shutdown(); System.out.println(submit.get()); System.out.println(submit.isDone()); System.out.println(submit.isCancelled()); }}

4. ParallelComputing //并行执行
public class T07_ParallelComputing { //计算1000000以内的质数 public static void main(String[] args) throws ExecutionException, InterruptedException { long start = System.currentTimeMillis(); ArrayList integers = get(1, 1000000); long end = System.currentTimeMillis(); System.out.println(end - start); //创建Callable线程实现 MyTask myTask = new MyTask(1, 20000); MyTask myTask1 = new MyTask(200001, 400000); MyTask myTask2 = new MyTask(400001, 600000); MyTask myTask3 = new MyTask(600001, 800000); MyTask myTask4 = new MyTask(800001, 1000000); ExecutorService pool = Executors.newFixedThreadPool(5); Future> submit = pool.submit(myTask); Future> submit1 = pool.submit(myTask1); Future> submit2 = pool.submit(myTask2); Future> submit3 = pool.submit(myTask3); Future> submit4 = pool.submit(myTask4); start = System.currentTimeMillis(); submit.get(); submit1.get(); submit2.get(); submit3.get(); submit4.get(); end = System.currentTimeMillis(); System.out.println(end - start); pool.shutdown(); } static class MyTask implements Callable> { int start, end; public MyTask(int start, int end) { this.start = start; this.end = end; } @Override public List call() throws Exception { return get(start, end); } } public static boolean isPrime(int num) { for (int i = 2; i <= num / 2; i++) if (num % 2 == 0) return false; return true; } public static ArrayList get(int start, int end) { ArrayList arrayList = new ArrayList<>(); for (int i = start; i <= end; i++) { if (isPrime(i)) arrayList.add(i); } return arrayList; }}

5. CachedPool
缓存线程池(Executors.newCachedThreadPool()),当有任务来线程池无空闲线程就会创建(默认无上限),但可以设置,默认当执行完的线程空闲60S自动关闭
public class T08_CachedPool { public static void main(String[] args) throws InterruptedException { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); System.out.println(cachedThreadPool); for (int i = 0; i < 3; i++) {cachedThreadPool.execute(() -> System.out.println(Thread.currentThread().getName())); } System.out.println(cachedThreadPool); TimeUnit.SECONDS.sleep(70); System.out.println(cachedThreadPool); cachedThreadPool.shutdown(); }}

6. SinglePool (Executors.newSingleThreadExecutor()) 线程池内就一个线程
7.ScheduledPool (Executors.newScheduledThreadPool(3))
public class T10_ScheduledPool { public static void main(String[] args) { ScheduledExecutorService pool = Executors.newScheduledThreadPool(3); //定时执行的线程池,有四个参数:接口,初始延迟,执行期间,时间单位 pool.scheduleAtFixedRate(() -> { try { TimeUnit.MILLISECONDS.sleep(new Random().nextInt(100)); } catch (InterruptedException e) {e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); },0,300, TimeUnit.MILLISECONDS); } }

8.WorkStealingPool (Executors.newWorkStealingPool()) 窃取
该线程池,每个线程都维护自己的任务队列,当执行完自己队列里面的线程 会去偷其他线程内的任务执行
可以传int 参数,默认不传根据CPU核数启动线程数
这是个精灵线程 daemo,内部是封装的 ForkJoinPool
9. ForkJoinPool 下面两个都是递归的思想 进行拆分
RecursiveAction //无返回值
RecursiveTask //有返回值
[例子如下 T12_ForkJoinPool ]
public class T12_ForkJoinPool {
static int[] nums = new int[100000]; static int maxNum = 5000; static Random random = new Random(); static { //初始化数组 for (int i = 0; i < nums.length; i++) nums[i] = random.nextInt(100); System.out.println(Arrays.stream(nums).sum()); } public static void main(String[] args) throws Exception { ForkJoinPool joinPool = new ForkJoinPool(); /* MyTask task = new MyTask(0, nums.length); joinPool.execute(task); //无返回值 System.out.println("*******************************"); */ MyTask2 task2 = new MyTask2(0, nums.length); ForkJoinTask joinTask = joinPool.submit(task2); System.out.println(joinTask.get()); //有返回值 joinPool.shutdown(); //System.in.read(); //因为是守护线程会在后台运行 }static class MyTask extends RecursiveAction { int start, end; public MyTask(int start, int end) { this.start = start; this.end = end; } @Override protected void compute() { //递归切分逻辑 if (end - start <= 5000) { long sum = 0; for (int i = start; i < end; i++) sum += nums[i]; System.out.println("start:" + start + " end:" + end + " sum:" + sum); } else { int middle = start + (end - start) / 2; MyTask task1 = new MyTask(start, middle); MyTask task2 = new MyTask(middle, end); task1.fork(); task2.fork(); }}} static class MyTask2 extends RecursiveTask { int start, end; public MyTask2(int start, int end) { this.start = start; this.end = end; } @Override protected Long compute() { //递归切分逻辑 if (end - start <= 5000) { long sum = 0; for (int i = start; i < end; i++) sum += nums[i]; return sum; } else { int middle = start + (end - start) / 2; MyTask2 task1 = new MyTask2(start, middle); MyTask2 task2 = new MyTask2(middle, end); task1.fork(); task2.fork(); return task1.join() + task2.join(); }}}}

    推荐阅读