为什么要用线程池
1.为什么要用线程池
多线程的情况下确实可以最大限度发挥多核处理器的计算能力,提高系统的吞吐量和性能。但是如果随意使用线程,对系统的性能反而有不利影响。
比如说
new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}}).start();
这样直接创建线程,在简单应用里面看起来没有问题,创建了一个线程,并且在run()方法结束后自动回收该线程。但是如果在真实系统里面,可能会由于业务情况,开启了很多线程,当线程数量多大时,反而会耗尽cpu和内存资源。
比如说,创建和销毁线程也需要时间,如果创建和销毁的时间远大于线程执行的时间,反而得不偿失。
其次线程也需要占用内存空间,大量的线程会抢占宝贵的内存资源,可能会导致out of memory异常。
且大量的线程回收也会给GC带来很大的压力,延长GC的停顿时间。
比如说 开启10000000个线程的时候
for (int i = 0; i <10000000; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}}).start();}
Exception in thread “main” java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:717)
at demo4.ThreadDemo.main(ThreadDemo.java:17)
所以千万要警惕这种情况的发生
最后,大量的线程也会抢占cpu的资源,cpu不停的在各个线程上下文切换中,反而没有时间去处理线程运行的时候该处理的任务。
因此,为了避免频繁的创建和销毁线程,让创建的线程进行复用,就有了线程池的概念。
线程池里会维护一部分活跃线程,如果有需要,就去线程池里取线程使用,用完即归还到线程池里,免去了创建和销毁线程的开销,且线程池也会线程的数量有一定的限制。
比如说刚刚的代码,通过使用线程池来构建线程
ExecutorService executorService= Executors.newFixedThreadPool(10);for (int i = 0; i <10000000; i++) {Thread t= new Thread(new Runnable() {@Overridepublic void run() {try {System.out.println("启动线程");Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}});executorService.submit(t);}}
可以看到,将不会再产生out of memory的错误,因为每次将只有10个线程在启用,其余的放在线程池内的任务队列里面。
这是使用线程池的好处之一。
但是线程池也分很多种,要视情况使用,newFixedThreadPool内部的任务队列是无界队列,如果放到的任务过多,最终也会导致内存不足。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
