最近复习Java多线程的时候, 发现一个问题, 使用synchronized锁时, CPU从头到尾只调度一个线程去执行, 其他两个线程似乎没有什么用:
package com.gyb.thread;
public class SynDemo01 {
/**
* @param args
*/
public static void main(String[] args) {
// 初始化线程类
Web12306 web = new Web12306();
// 代理
Thread t1 = new Thread(web, "路人甲");
Thread t2 = new Thread(web, "黄牛已");
Thread t3 = new Thread(web, "攻城师");
// 启动线程
t1.start();
t2.start();
t3.start();
}
}
/**
* 线程安全的类
*
* @author Administrator
*
*/
class Web12306 implements Runnable {
private Integer num = 10;
private boolean flag = true;
@Override
public void run() {
while (flag) {
test2();
}
}
// 线程安全 锁定正确
public synchronized void test2() {
if (num <= 0) {
flag = false; // 跳出循环
return ;
}
try {
// 模拟 延时
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
}
}
输出结果:
路人甲抢到了10
路人甲抢到了9
路人甲抢到了8
路人甲抢到了7
路人甲抢到了6
路人甲抢到了5
路人甲抢到了4
路人甲抢到了3
路人甲抢到了2
路人甲抢到了1
测试与解决:
-
方法① 将num由10改为1000, 输出结果, 可以看到8700多的时候CPU才调度的名为’黄牛’的线程:
方法② 在synchronized同步方法或同步块之前再增加一个sleep方法:
结果与猜想: -
这个跟CPU性能有关, 完全一致的代码在我的电脑和公司的电脑上, 发现CPU对线程调度与执行速度不一致,
-
上面的方法① 实际测试过,性能好的CPU需要大量增加线程循环执行次数, 我的机器上是10000次), 才能看到其他线程的执行,
而公司的电脑只要循环10次, 就能看到别的线程执行了(说明好的CPU单个线程更牛X?) -
上面的方法② 当sleep在synchronized同步方法或同步块之外的时候,三个线程都有执行, 是因为sleep方法会给其他线程运行的机会,而不管其他线程的优先级, (但在synchronized同步方法里的sleep, 由于被锁住所以没有优先级之说, 也就是说synchronized同步方法里的sleep失效了, 这是我的猜想)
-
想看到线程具体的执行过程,可以打开JDK bin目录下的jvisualvm.exe 监视JavaJVM的状态,如图:
有不足之处请指出, 转载请注明出处, 谢谢~!