多线程环境下的static静态方法和类方法

平菇虾饺 2014-08-24 09:48:14
加精
今天无意之中看到一篇讨论静态方法和类方法的帖子。于是就想着测一测,遇到了部分问题。希望有大神能给解答一下

我的java代码:

包:isStatic
Method.java

package isStatic;

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class Method {

public static void littlelong1(String name) {
long i = 0;
while (i ++ != 100000000l) {
//do nothing , but not sleep
}
}

public void littlelong2(String name) {
long i = 0;
while (i ++ != 100000000l) {
//do nothing , but not sleep
}
}
/*这是为了我测试方便,可以删掉的*/
public static int getConfig() {
Properties p = new Properties();
try {
p.load(new FileReader("pro.properties"));
} catch (IOException e) {
e.printStackTrace();
}
return Integer.parseInt(p.getProperty("LENGTH"));
}
}

UseLittlelong.java

package isStatic;

public class UseLittlelong {

private static int LENGTH = 20;
private int[] avg_static = new int[LENGTH];
private int[] avg_nonstatic = new int[LENGTH];
//divided
private Method m = new Method();

public static void main(String[] args) {
UseLittlelong ull = new UseLittlelong();
ull.staticTest();
ull.nonstaticTest();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ull.avg();
}
/*test static*/
public void staticTest() {
int i = -1 ;
/*原谅我选择了再循环中启动线程,只是这样显得更方便一些*/
while (i ++ < LENGTH - 1) {
new Use(true,i).start();
}
}
/*test non-static*/
public void nonstaticTest() {
int i = -1 ;
while (i ++ < LENGTH - 1) {
new Use(false,i).start();
}
}
/*average count*/
public void avg() {
long sta = 0,nonsta = 0;

for (int i = 0 ; i < LENGTH; i++) {
sta += avg_static[i];
nonsta += avg_nonstatic[i];
}

System.out.println("static avg :" + sta / LENGTH);
System.out.println("non-static avg :" + nonsta / LENGTH);
}

/**
* @author qyp199312
*/
class Use extends Thread {

private boolean isStatic;
private String threadName;
private int threadId;

public Use(boolean b,int threadId) {
this.isStatic = b;
this.threadId = threadId;
this.threadName = (b ? "[static-" : "[nonstatic-")+ threadId +"] ";
}

public void run () {
if (isStatic) {
long begin = System.currentTimeMillis();
Method.littlelong1(threadName);
avg_static[threadId] = (int) (System.currentTimeMillis() - begin);
// System.out.println(threadName + avg_static[threadId] );
} else {
long begin = System.currentTimeMillis();
// new Method().littlelong2(threadName);
m.littlelong2(threadName);
avg_nonstatic[threadId] = (int) (System.currentTimeMillis() - begin);
// System.out.println(threadName + avg_nonstatic[threadId] );
}
}
}
}

pro.properties

#可在源码中置换为实际数字
LENGTH = 20

我在本机上(i5-4300U 1.9GHz 8G)跑出来的结果为:

static avg :602
non-static avg :280

我在服务器上(Intel(R) Xeon(R) CPU E5520 @ 2.27GHz 48G)跑多次出来的结果为:

[tt ~]$ java isStatic/UseLittlelong
static avg :438
non-static avg :505
[tt ~]$ java isStatic/UseLittlelong
static avg :439
non-static avg :480
[tt ~]$ java isStatic/UseLittlelong
static avg :486
non-static avg :526
[tt ~]$ java isStatic/UseLittlelong
static avg :337
non-static avg :448
[tt ~]$ java isStatic/UseLittlelong
static avg :460
non-static avg :517
[tt ~]$ java isStatic/UseLittlelong
static avg :369
non-static avg :466
[tt ~]$ java isStatic/UseLittlelong
static avg :402
non-static avg :441
[tt ~]$ java isStatic/UseLittlelong
static avg :462
non-static avg :498
[tt ~]$ java isStatic/UseLittlelong
static avg :372
non-static avg :433


疑问:
1.修改线程数,得到的时间近似正比翻倍。而按理说排除掉多线程分担掉的cpu消耗,不管多少个线程执行平均时间应该是近似相等的。这是我的程序的BUG还是其他什么的原因?
2.忽略掉本机和服务器性能差异,静态方法调用和非静态方法的调用时间占比应该差不多。而明显的,本机上静态方法调用时间占用较大,而服务器上类方法的调用时间占用较大。这又是为什么。
服务器jdk:
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
本机jdk
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)


集思广益,求大神们踊跃发言。让更多的人看见,让更多的人明白。
...全文
9510 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq948216248 2015-12-26
  • 打赏
  • 举报
回复
楼主发现是什么问题了吗?我也遇到了,加入关键字synchronized后,每个线程运行时间就跟原来单线程的差不多,总的时间和不加synchronized时间差不多
乾坤幻影 2014-09-03
  • 打赏
  • 举报
回复
这么专业的讨论,学习了
flyzxs 2014-09-02
  • 打赏
  • 举报
回复
好专业 谢谢
伊顺鸣 2014-09-01
  • 打赏
  • 举报
回复
干啥去了啊。。
shanhaizhoutian 2014-08-29
  • 打赏
  • 举报
回复
遇到一个对我来说老难的问题 真心不知道该怎么解决 首先 有一张表A 字段有 编号 ,名称 ,卡号是两位的char类型 有一个页面B在进入时 显示 主要这么几部分 : 1 学号输入栏 2 查询按纽 3 各种个人信息 4 很多个多选框 5 提交按纽 以上中的 很多个多选框对应的内容就是 A表中的名称 大家可以理解成 A表是个商品表 譬如说 电脑 手机 键盘 鼠标 等等 以后会不断加入新的 数据 刚进入页面B的时候,所有数据栏都是空的, 多选框显示出A表的所有名称 有多少个名称就有多少个 多选框,一个框都没有勾选。 之后在 学号输入栏输入 学号 ,点击查询 ,会在C表中根据学号查出一条数据,里面有一个字段100位,用来存放 ,勾选了的商品的对应编号的。 譬如说之前有个一条数据 ,是 学号001 姓名 李三 的数据 里面一个字段 是 M4T8 ,在后台action里 把M4T8 两两位切开, 也就是 M4 , T8, 这时前台B页面里 对应的 M4的 手机和 T8的 鼠标 选框就会被勾上。。。 关键是这里 以前一般的 写死的 固定的 多选框 都是一个多选框对应一个name,每个name都在form里有对应属性,通过form来在后台action传递到前台。。。可是这次的name是不确定的 该怎么办呢
zhglance 2014-08-29
  • 打赏
  • 举报
回复
”不应该取系统时间相加减,而要看该线程CPU运行时间“ 怎样才能够去线程的运行时间?
梅红王子 2014-08-28
  • 打赏
  • 举报
回复
学习一下。。。。。。。。。。。。
纳兰弦歌 2014-08-27
  • 打赏
  • 举报
回复
张姿势了. 不过看的迷迷糊糊的....好多没看懂...
庚武讲堂 2014-08-27
  • 打赏
  • 举报
回复
引用 24 楼 qyp199312 的回复:
第二个问题中两个系统的时间处理差异倒不是什么大问题。我最初的想法是测验出多线程环境下工具类究竟是静态方法好还是实例方法好。如果真的是系统相关的话,究竟部署在什么样的系统上使用什么样的模式更好。还望多指教啊~
我个人的理解,静态方法和类方法效率是非常相近的,其中的取舍不应该在于软件环境(OS,JRE等,那不是java应用程序员所能控制的),而应在于系统框架设计,忽略这一点小小性能差异吧,更灵活的设计是正道。 像Spring框架定义singleton模式的服务类,不也是经常用吗?谁说它不好呢,非要全用静态? 像某些Util类全是静态,用起来方便,不需要实例化。谁说它不好呢,非要全用实例方法?
鬼火儿 2014-08-27
  • 打赏
  • 举报
回复
哎,我发现这里的大神真多,没事可以来学习,学习。菜鸟,求带!!
GW786228836 2014-08-27
  • 打赏
  • 举报
回复
少侠请留步☆ 2014-08-27
  • 打赏
  • 举报
回复
看不懂▪▪▪▪▪▪▪▪▪▪▪▪☏☏☏☏☏☏
平菇虾饺 2014-08-26
  • 打赏
  • 举报
回复
引用 23 楼 stupid_boy2007 的回复:
第一个问题很容易解释的: 操作系统是分时多任务系统,同时20个线程各完成N量的工作,与同时30线程各完成N量,CPU分配得线程更多,平均完成的时间当然越长。 举例:设每线程完成N量工作需要5单位时间,现在同一CPU分配20份去做,第二次分配30份去做,当然30份的时间长,因为其它不在运行态的线程要等得更久。 楼主的逻辑错误在于,不应该取系统时间相加减,而要看该线程CPU运行时间,这样才是合理的。 long begin = System.currentTimeMillis(); Method.littlelong1(threadName); avg_static[threadId] = (int) (System.currentTimeMillis() - begin); 不过不知道java中有无方法取得。 第二个问题可能与系统有关,我的运行结果,有时多,有时少,有随机性。 20 thead: static avg :1598 non-static avg :1573 20 thead: static avg :1485 non-static avg :1449 30 thread: static avg :1929 non-static avg :1975 40 thread: static avg :3113 non-static avg :3092 最后说句,看来我的win7 64bit + i3 + 8G 的配置落伍了啊!!
第一个问题我算是明白了,你说得很对。可能一个时间片很短很短短到远低于50MS,因此多个排队自然会导致正比形式的时间增长。 看了半天算是把第一个问题看明白了。 第二个问题中两个系统的时间处理差异倒不是什么大问题。我最初的想法是测验出多线程环境下工具类究竟是静态方法好还是实例方法好。如果真的是系统相关的话,究竟部署在什么样的系统上使用什么样的模式更好。还望多指教啊~
庚武讲堂 2014-08-26
  • 打赏
  • 举报
回复
第一个问题很容易解释的: 操作系统是分时多任务系统,同时20个线程各完成N量的工作,与同时30线程各完成N量,CPU分配得线程更多,平均完成的时间当然越长。 举例:设每线程完成N量工作需要5单位时间,现在同一CPU分配20份去做,第二次分配30份去做,当然30份的时间长,因为其它不在运行态的线程要等得更久。 楼主的逻辑错误在于,不应该取系统时间相加减,而要看该线程CPU运行时间,这样才是合理的。 long begin = System.currentTimeMillis(); Method.littlelong1(threadName); avg_static[threadId] = (int) (System.currentTimeMillis() - begin); 不过不知道java中有无方法取得。 第二个问题可能与系统有关,我的运行结果,有时多,有时少,有随机性。 20 thead: static avg :1598 non-static avg :1573 20 thead: static avg :1485 non-static avg :1449 30 thread: static avg :1929 non-static avg :1975 40 thread: static avg :3113 non-static avg :3092 最后说句,看来我的win7 64bit + i3 + 8G 的配置落伍了啊!!
老衲是光头 2014-08-26
  • 打赏
  • 举报
回复
「已注销」 2014-08-26
  • 打赏
  • 举报
回复
不觉而历
GW786228836 2014-08-26
  • 打赏
  • 举报
回复
mienyule 2014-08-26
  • 打赏
  • 举报
回复
额。。。。怎么一按回车就提交了。关于第4点补充一下: 4.楼主说的第2点结论可能是因为JVM工作模式不同导致的,也可能是因为你服务器的多核CPU给线程并行执行导致的; 对于楼主说的第一点结论,个人认为并不是“修改线程数,得到的时间近似正比翻倍”,也不是“不管多少个线程执行平均时间应该是近似相等的”,而是应该类似抛物线,在某一点CPU资源和JVM线程得到最合理的分配,在这之前线程数和CPU执行时间是成正比;而这之后线程数和CPU执行时间是成反比的,因为过多的线程导致CPU时间片的分配越来越激烈,内存资源可能会被耗尽,线程间频繁的上下文切换也很耗资源; [/quote] 你所指的情况确实出现了,不过不是抛物线。 起始情况为单个线程执行时间与线程数近似正比。等待增加到一定线程数的时候正比值就逐渐放缓了。 只有等到需要多个时间片轮或者是内存耗尽或者是其他什么的原因的时候,执行时间大幅度上升。但这不是我们讨论的范围了。‘ 可是起始情况我仍然不是很明白(正比是怎么来的)[/quote] 楼上应该有提到过,是因为线程数和CPU内核(线程)数之关的关系。 因为一个线程只能跑在一个CPU核上,如果线程数<CPU内核数,你新创线程,还有空的CPU内核可以分配,所以能得到提升。 一旦超过,多创线程只会创造争用,增加开销。[/quote]
zapdos 2014-08-26
  • 打赏
  • 举报
回复
这样测说明不了什么问题
平菇虾饺 2014-08-25
  • 打赏
  • 举报
回复
引用 7 楼 gaofuqi 的回复:
额。。。。怎么一按回车就提交了。关于第4点补充一下: 4.楼主说的第2点结论可能是因为JVM工作模式不同导致的,也可能是因为你服务器的多核CPU给线程并行执行导致的; 对于楼主说的第一点结论,个人认为并不是“修改线程数,得到的时间近似正比翻倍”,也不是“不管多少个线程执行平均时间应该是近似相等的”,而是应该类似抛物线,在某一点CPU资源和JVM线程得到最合理的分配,在这之前线程数和CPU执行时间是成正比;而这之后线程数和CPU执行时间是成反比的,因为过多的线程导致CPU时间片的分配越来越激烈,内存资源可能会被耗尽,线程间频繁的上下文切换也很耗资源;
你所指的情况确实出现了,不过不是抛物线。 起始情况为单个线程执行时间与线程数近似正比。等待增加到一定线程数的时候正比值就逐渐放缓了。 只有等到需要多个时间片轮或者是内存耗尽或者是其他什么的原因的时候,执行时间大幅度上升。但这不是我们讨论的范围了。‘ 可是起始情况我仍然不是很明白(正比是怎么来的)
加载更多回复(16)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧