线程池的使用
一:为什么使用线程池
当任务量比较大时,我们会创建多个线程来同时处理任务,这样就有创建线程、使用线程、销毁线程的过程,
当创建线程和销毁线程所占用的资源大于使用线程时,我们就会考虑使用线程的内存问题,于是线程池便诞生了。
线程池里面可以创建多个线程,如果有需求时,可以直接从线程池中取线程处理任务,需求处理完毕时,在释放
线程,放回到线程池中。
二:使用线程池
1:创建可以缓存的线程池
这种方式会每隔1s打印一个数字,会创建多个线程,比如第一个线程输出1,第一个线程被阻塞,第二个线程输出2,第二个线程被阻塞,
然后...,等到第三个线程输出3时,第一个线程会被释放掉,输出4,然后又被阻塞,... 一旦被阻塞,就会启动新的线程。
1 /*** 2 * 不定长线程,如果线程长度大于任务数量时,可以回收空闲的线程;如果线程长度小于任务数量时, 会创建新的线程 3 */ 4 public static void testCacheThreadPool() { 5 ExecutorService executors = Executors.newCachedThreadPool(); 6 for (int i = 0; i < COUNT; i++) { 7 final int index = i; 8 executors.execute(new Runnable() { 9 10 @Override 11 public void run() { 12 try { 13 Thread.sleep(index * 1000); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 System.out.println(index + " "+ Thread.currentThread().getName()); 18 } 19 20 }); 21 } 22 }
因为之前阻塞的线程一直没有被释放,所以一直创建新的线程来处理任务:
1 0 pool-1-thread-1 2 1 pool-1-thread-2 3 2 pool-1-thread-3 4 3 pool-1-thread-4 5 4 pool-1-thread-1 6 5 pool-1-thread-5 7 6 pool-1-thread-6 8 7 pool-1-thread-7 9 8 pool-1-thread-8 10 9 pool-1-thread-9
调整代码,把阻塞放在线程池执行任务前面,这样第一个线程输出1,然后释放掉,阻塞1秒,线程1会输出2,然后在释放掉,被放回
线程池中,....... 然后是一直 线程1 在执行任务
1 public static void testCacheThreadPool() { 2 ExecutorService executors = Executors.newCachedThreadPool(); 3 for (int i = 0; i < COUNT; i++) { 4 final int index = i; 5 try { 6 Thread.sleep(index * 1000); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 } 10 11 executors.execute(new Runnable() { 12 @Override 13 public void run() { 14 System.out.println(index + " " 15 + Thread.currentThread().getName()); 16 } 17 }); 18 } 19 }
打印结果:
1 0 pool-1-thread-1 2 1 pool-1-thread-1 3 2 pool-1-thread-1 4 3 pool-1-thread-1 5 4 pool-1-thread-1 6 5 pool-1-thread-1 7 6 pool-1-thread-1 8 7 pool-1-thread-1 9 8 pool-1-thread-1 10 9 pool-1-thread-1
2:创建固定数量的线程池
线程池中线程数量固定,如果处理任务超出线程长度,那么就会一直处于队列中