java线程与线程池_java线程池和创建java线程性能比较

前面几篇文章我们一直在讲述java线程池的相关知识点,我相信现在大家对java多线程一定有了一些了解,jdk中的核心实现类为java.util.concurrent.ThreadPoolExecutor,前面大家了解到它的原理(可查看:http://www.cuiyongzhi.com/index.php/post/72.html  ),看过它的源码(可查看:http://www.cuiyongzhi.com/index.php/post/71.html  );但是就像我一样,大家可能对它的作用存在误解;现在问题来了,jdk为什么要提供java线程池?使用java线程池对于每次都创建一个新Thread有什么优势?下面我们就一一来验证这些我们心中的疑虑!

很长一段时间里我一直以为java线程池是为了提高多线程下创建线程的效率。创建好一些线程并缓存在线程池里,后面来了请求(Runnable)就从连接池中取出一个线程处理请求;这样就避免了每次创建一个新Thread对象。直到前段时间偶尔我看到Neal Gafter(和Joshua Bloch合著了《Java Puzzlers》,现任职于微软,主要从事.NET语言方面的工作)的访谈中有提到下面这样一句话:

94572c30d97c780746a8f72b1b09c1bb.png

乍一看,大神的思路就是不一样:java线程池是为了防止java线程占用太多资源?Java大神说占资源,那么我们就来看看是不是这么玩的!

①在验证大牛的占用资源的观点之前先验证下我的理解:java线程池和创建java线程哪个效率高?下面直接上测试代码:

package com.cuiyongzhi.io;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import junit.framework.TestCase;

/*

* java线程对比

*/

public class ThreadPoolTest extends TestCase {

private static final int COUNT = 10000;

/**

* @Description: java线程池实现

* @param @throws InterruptedException

* @author dapengniao

* @date 2016年4月14日 上午10:16:23

*/

public void testThreadPool() throws InterruptedException {

CountDownLatch countDownLatch = new CountDownLatch(COUNT);

ExecutorService executorService = Executors.newFixedThreadPool(100);

long bg = System.currentTimeMillis();

for (int i = 0; i < COUNT; i++) {

Runnable command = new TestRunnable(countDownLatch);

executorService.execute(command);

}

countDownLatch.await();

System.out.println("testThreadPool:" + (System.currentTimeMillis() - bg));

}

/**

* @Description: 创建java线程实现

* @param @throws InterruptedException

* @author dapengniao

* @date 2016年4月14日 上午10:16:31

*/

public void testNewThread() throws InterruptedException {

CountDownLatch countDownLatch = new CountDownLatch(COUNT);

long bg = System.currentTimeMillis();

for (int i = 0; i < COUNT; i++) {

Runnable command = new TestRunnable(countDownLatch);

Thread thread = new Thread(command);

thread.start();

}

countDownLatch.await();

System.out.println("testNewThread:" + (System.currentTimeMillis() - bg));

}

private static class TestRunnable implements Runnable {

private final CountDownLatch countDownLatch;

TestRunnable(CountDownLatch countDownLatch) {

this.countDownLatch = countDownLatch;

}

@Override

public void run() {

countDownLatch.countDown();

}

}

}

在代码中我们添加了计时,这里使用Executors.newFixedThreadPool(100)是为了控制线程池的核心连接数和最大连接数一样大,都为100,我的机子上的测试结果:

50edb8f72b4937c69c8603976020e081.png

可以看到,使用线程池处理10000个请求的处理时间为45ms,而每次启用新线程的处理时间为939ms,好了,使用线程池确实要比每次都创建新线程要快一些;但是如果按照大牛的说法这点时间应该根本不算什么,所以下面我们来验证下大牛的资源占用问题!

②java线程池是为了节约资源?再来测试代码如下:

package com.cuiyongzhi.io;

import junit.framework.TestCase;

/**

* ClassName: ThreadPoolTestTwo

* @Description: 用java不断创建新线程,查看jvm内存变化

* @author dapengniao

* @date 2016年4月14日 上午10:53:08

*/

public class ThreadPoolTestTwo extends TestCase {

public void testThread() throws InterruptedException {

int i = 1;

while (true) {

Runnable command = new TestRunnable();

Thread thread = new Thread(command);

thread.start();

System.out.println(i++);

}

}

private static class TestRunnable implements Runnable {

@Override

public void run() {

try {

Thread.sleep(100000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

当我们运行代码的时候我么查看jvm内存变化,我们会发现会追随者线程数增多而jvm上涨,停下来jvm也跟着停下来,或许机器弱点的话可能就会OOM(java.lang.OutOfMemoryError: unable to create new native thread)了,运行过程中如下:

8eb476fcae97e298e69a56ccf86734c9.gif

至于为什么会抛OOMError?因为jvm会为每个线程分配一定内存(JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K,也可以通过jvm参数-Xss来设置),所以当线程数达到一定数量时就报了该error!设想如果不使用java线程池,而为每个请求都创建一个新线程来处理该请求,当请求量达到一定数量时一定会内存溢出的;而我们使用java线程池的话,线程数量一定会<=maximumPoolSize(线程池的最大线程数),所以设置合理的话就不会造成内存溢出!

所以执行一个异步任务你还只是使用new Thread,那你就out太多了,最后总结下:

A.new Thread的弊端

每次new Thread新建对象性能差。

线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。

缺乏更多功能,如定时执行、定期执行、线程中断。

B.Java提供的四种线程池的好处

重用存在的线程,减少对象创建、消亡的开销,性能佳。

可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

提供定时执行、定期执行、单线程、并发数控制等功能。

----------本文来源于网络学习,感谢你的翻阅,如有疑问可以留言讨论!

除非注明,否则文章均由 崔用志博客 整理发布,欢迎转载。

如果喜欢,可以点此订阅本站

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值