美文网首页
Java中使用线程池的效率对比和异步执行函数的参数问题

Java中使用线程池的效率对比和异步执行函数的参数问题

作者: hexter | 来源:发表于2021-04-10 16:18 被阅读0次

先说结论:

1,如果需要很多线程执行任务,每个任务都不大的话,用线程池性能提升很高,10几倍左右。

2,线程池开的线程不用太多,和机器cpu内核量差不多就行。

3,如果有函数是被异步调用执行的话,要注意给它传入的参数,可能在函数执行时并不是你当初预想的参数值。

-------------------------------------------------------------------------------------------------------------------------------

贴对比的代码:

public class TestMain {

static final int TNum=10000;

static int i=0;

//用线程池

public void UseThreadPool(int count) {

long startTime = System.currentTimeMillis();

ThreadPoolExecutor tp = new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS,

new LinkedBlockingQueue(count));

for (i= 0; i < count; i++) {

tp.execute(new Runnable() {

@Override

public void run() {

fun0( );

}

});

}

tp.shutdown();

try {

tp.awaitTermination(1, TimeUnit.DAYS);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.print("使用了线程池:");

System.out.println(System.currentTimeMillis() - startTime + "毫秒");

}

//不用线程池

public void unUseThreadPool(int count) {

long startTime = System.currentTimeMillis();

for ( i = 0; i < count; i++) {

Thread thread = new Thread() {

public void run() {

fun0();

}

};

thread.start();

try {

thread.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.print("未用线程池:");

System.out.println(System.currentTimeMillis() - startTime + "毫秒");

}

public static void main(String[] args) {

TestMain testpool = new TestMain();

testpool.UseThreadPool(TNum);

testpool.unUseThreadPool(TNum);

}

private Double fun0()

{

Random random = new Random();

String buf="abc"+random.nextDouble();

Double result=random.nextDouble()*random.nextDouble()*random.nextDouble();

int ak=0;

for (int i=1;i<100;i++)

{

ak=ak+i;

}

return result;

}

}

上面的代码线程池是4个线程,最多8个,执行后结果如下:

效果蛮好的,用了线程池性能提高10几倍。

我把线程池加大线程数量,到40个线程,最高80个,结果如下

这个和4线程差异不大,在变动范围内。

如果继续加大线程池开到4000个线程。则性能暴跌了

说明线程池的线程不用太对,估计只要和电脑cpu的核数量匹配就行。

----------------------------------------------------------------------------------------

然后,我想会不会是用了线程池后,线程没执行完就统计时间导致看起来性能高。

然后,我把上面的fun0()函数改了一下fun1:

private Double fun1(int par)

{

Random random = new Random();

String buf="abc"+random.nextDouble();

Double result=random.nextDouble()*random.nextDouble()*random.nextDouble();

int ak=0;

for (int i=1;i<100;i++)

{

ak=ak+i;

}

//if(par==(TNum-1))

{System.out.println("TNum:"+par);}

return result;

}

//用线程池的

for (i= 0; i < count; i++) {

{System.out.println("TNuma:"+(i+1));}

tp.execute(new Runnable() {

@Override

public void run() {

{System.out.println("TNumb:"+(i+1));}

fun1(i);

}

});

}

//不用线程池

for ( i = 0; i < count; i++) {

Thread thread = new Thread() {

public void run() {

//fun0();

fun1(i);

}

};

thread.start();

try {

thread.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

使用线程池的输出这样:

我原本希望fun1()收到的参数是0 1 2 3,但是看TNum的输出4个线程分别受到的参数是4 4 2 4。而从打印的TNuma 和TNumb的数据能看出,线程池里的线程是被异步执行的。正是因为线程池的execute()函数是异步的,它收到runnable后放入队列,所以for循环迅速执行完。

而线程池开始执行队列里的runnable的时候,才开始去调用fun1,并压入参数par,而这个时候i已经变了,并不是当初设想的0 1 2 3 了。

而未用线程池的输出是对的 

-------------------------------------------------------------------------------------

所以对于被异步调用执行的函数,对它的参数需要单独保存

我这样改了一下

class MyRunnable implements Runnable{

public int par;

public MyRunnable(int par)

{

this.par=par;

}

@Override

public void run() {

// TODO Auto-generated method stub

fun1(par);

}

}

然后

//线程池

for (i= 0; i < count; i++) {

tp.execute(new MyRunnable(i));

}

//未用线程池

for ( i = 0; i < count; i++) {

Thread thread = new Thread(new MyRunnable(i)) ;

thread.start();

try {

thread.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

这样参数就正常了

相关文章

  • Java中使用线程池的效率对比和异步执行函数的参数问题

    先说结论: 1,如果需要很多线程执行任务,每个任务都不大的话,用线程池性能提升很高,10几倍左右。 2,线程池开的...

  • Java线程池

    一、线程池简介 线程的使用在Java中占有重要的地位,尤其是在执行耗时操作(Java网络编程)和异步访问(SWT中...

  • 并发编程09--Java中的线程池

    Java中的线程池 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程...

  • Oozie-Service-CallableQueueServi

    Oozie 使用 CallableQueueService 来异步执行操作; 特点: 参数说明: 线程池选取的队列...

  • java并发基础-线程池

    线程池主要解决两个问题:当执行大量异步任务时线程池能够提供较好的性能。在不使用线程池时,每当需要执行异步任务时直接...

  • 线程池

    线程池的好处 Java 中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。...

  • ThreadPoolExecutor 源码解析

    Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序 都可以使用线程池。合理地使用线程...

  • 多线程(五)——线程池原理剖析&锁的深度化

    什么是线程池 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。在...

  • 5.线程池原理剖析&锁的深度化

    线程池 什么是线程池 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线...

  • 并发 - Java中的线程池

    线程池 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过...

网友评论

      本文标题:Java中使用线程池的效率对比和异步执行函数的参数问题

      本文链接:https://www.haomeiwen.com/subject/fljnkltx.html