java 多线程 例子 入门博文一
2013-07-19 17:03
281 查看
网上找的一些例子觉得不能说明问题,重写了一个主要来体现synchronized的效果
输出可能是这样的==============================================================
Thread-A : 当前dataCount对象的计算值= 70
Thread-A : 当前dataCount对象的计算值= 10
Thread-C : 当前dataCount对象的计算值= -50
Thread-C : 当前dataCount对象的计算值= -80
Thread-B : 当前dataCount对象的计算值= -110
Thread-C : 当前dataCount对象的计算值= -140
Thread-B : 当前dataCount对象的计算值= -140
Thread-A : 当前dataCount对象的计算值= -170
Thread-B : 当前dataCount对象的计算值= -170
改写DataCount之后
输出可能是这样的==============================================================
Thread-A : 当前dataCount对象的计算值= 70 第1次计算
Thread-B : 当前dataCount对象的计算值= 40 第2次计算
Thread-C : 当前dataCount对象的计算值= 10 第3次计算
Thread-A : 当前dataCount对象的计算值= -20 第4次计算
Thread-B : 当前dataCount对象的计算值= -50 第5次计算
Thread-C : 当前dataCount对象的计算值= -80 第6次计算
Thread-A : 当前dataCount对象的计算值= -110 第7次计算
Thread-B : 当前dataCount对象的计算值= -140 第8次计算
Thread-C : 当前dataCount对象的计算值= -170 第9次计算
这个顺序正是我们想要的,不论是哪个线程进行的第3次计算,第3次计算的结果就应该是10,
其他次计算也是要按这个顺序,这时synchronized的效果就看出来了。
接下来对几个现象进行讨论:
1、为什么不用synchronized之前,会出现非我们期望的输出顺序?
2、为什么不用synchronized之前,会出现2次-170,而没有出现-200?
这两个现象其实是同一个问题,
我们来把它的过程梳理一下
这个过程一共有3个线程,每个线程进行了3次计算,一共9次计算。
这9次计算分别是,
Thread-A对x减了3次30,记为TA-1,TA-2,TA-3
Thread-B对x减了3次30,记为TB-1,TB-2,TB-3
Thread-C对x减了3次30,记为TC-1,TC-2,TC-3
这9次计算哪些顺序是必然的?
TA-1一定先于TA-2,TA-2一定先于TA-3
TB-1一定先于TB-2,TB-2一定先于TB-3
TC-1一定先于TC-2,TC-2一定先于TC-3
其他的顺序都是偶然的,可以简单理解为线程内顺序,线程间乱序。
为什么会出现类似
Thread-A : 当前dataCount对象的计算值= 70
Thread-A : 当前dataCount对象的计算值= 10
这样的顺序?
当线程A执行x = x - y;这步操作完成后,可能被其他的线程再次执行x = x - y;然后又切换到线程A执行return x;
这时线程A得到的是两次x = x - y;后的结果,所以第二次返回了10而不是40。
然后解释为什么最后会出现两次-170,而不是在得到-170之后再出现-200呢?
因为一共只有9次计算,也就是最后的结果就是100-30*9=-170。所以不会出现-200。
那为什么会出现连续两次-170呢?线程A执行了x = x - y;之后轮到线程B执行x = x - y;然后轮到线程A执行return x;然后轮到线程B执行return x;
这时A和B得到了相同的返回结果。
大概就是这样。
public class TestRunnable implements Runnable { private DataCount dataCount = new DataCount(); public static void main(String[] args) { TestRunnable r = new TestRunnable(); Thread ta = new Thread(r, "Thread-A"); Thread tb = new Thread(r, "Thread-B"); Thread tc = new Thread(r, "Thread-C"); ta.start(); tb.start(); tc.start(); } public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + " : 当前dataCount对象的计算值= " + dataCount.count(30)); } } } public class DataCount { private int x = 100; public int count(int y) { x = x - y; for (int i = 0; i < 10000000; i++) { // 模拟耗时业务 } return x; } }
输出可能是这样的==============================================================
Thread-A : 当前dataCount对象的计算值= 70
Thread-A : 当前dataCount对象的计算值= 10
Thread-C : 当前dataCount对象的计算值= -50
Thread-C : 当前dataCount对象的计算值= -80
Thread-B : 当前dataCount对象的计算值= -110
Thread-C : 当前dataCount对象的计算值= -140
Thread-B : 当前dataCount对象的计算值= -140
Thread-A : 当前dataCount对象的计算值= -170
Thread-B : 当前dataCount对象的计算值= -170
改写DataCount之后
public class DataCount { private int x = 100; public int count(int y) { synchronized (this) { x = x - y; for (int i = 0; i < 10000000; i++) { // 模拟耗时业务 } return x; } } }
输出可能是这样的==============================================================
Thread-A : 当前dataCount对象的计算值= 70 第1次计算
Thread-B : 当前dataCount对象的计算值= 40 第2次计算
Thread-C : 当前dataCount对象的计算值= 10 第3次计算
Thread-A : 当前dataCount对象的计算值= -20 第4次计算
Thread-B : 当前dataCount对象的计算值= -50 第5次计算
Thread-C : 当前dataCount对象的计算值= -80 第6次计算
Thread-A : 当前dataCount对象的计算值= -110 第7次计算
Thread-B : 当前dataCount对象的计算值= -140 第8次计算
Thread-C : 当前dataCount对象的计算值= -170 第9次计算
这个顺序正是我们想要的,不论是哪个线程进行的第3次计算,第3次计算的结果就应该是10,
其他次计算也是要按这个顺序,这时synchronized的效果就看出来了。
接下来对几个现象进行讨论:
1、为什么不用synchronized之前,会出现非我们期望的输出顺序?
2、为什么不用synchronized之前,会出现2次-170,而没有出现-200?
这两个现象其实是同一个问题,
我们来把它的过程梳理一下
这个过程一共有3个线程,每个线程进行了3次计算,一共9次计算。
这9次计算分别是,
Thread-A对x减了3次30,记为TA-1,TA-2,TA-3
Thread-B对x减了3次30,记为TB-1,TB-2,TB-3
Thread-C对x减了3次30,记为TC-1,TC-2,TC-3
这9次计算哪些顺序是必然的?
TA-1一定先于TA-2,TA-2一定先于TA-3
TB-1一定先于TB-2,TB-2一定先于TB-3
TC-1一定先于TC-2,TC-2一定先于TC-3
其他的顺序都是偶然的,可以简单理解为线程内顺序,线程间乱序。
为什么会出现类似
Thread-A : 当前dataCount对象的计算值= 70
Thread-A : 当前dataCount对象的计算值= 10
这样的顺序?
当线程A执行x = x - y;这步操作完成后,可能被其他的线程再次执行x = x - y;然后又切换到线程A执行return x;
这时线程A得到的是两次x = x - y;后的结果,所以第二次返回了10而不是40。
然后解释为什么最后会出现两次-170,而不是在得到-170之后再出现-200呢?
因为一共只有9次计算,也就是最后的结果就是100-30*9=-170。所以不会出现-200。
那为什么会出现连续两次-170呢?线程A执行了x = x - y;之后轮到线程B执行x = x - y;然后轮到线程A执行return x;然后轮到线程B执行return x;
这时A和B得到了相同的返回结果。
大概就是这样。
相关文章推荐
- java多线程入门例子-第一例
- java多线程入门例子
- java 多线程 synchronized 入门博文二
- JAVA中建立多线程的典型例子
- 当年第一次学习java多线程写的例子,从此多线程不再陌生
- java一个多线程的经典例子
- Java一个多线程的经典例子
- JAVA多线程入门
- spark入门cogroup简单例子(JAVA)
- spark入门cogroup简单例子(JAVA)
- [Java基础]多线程求和小例子
- java多线程的常见例子
- Java 多线程入门大全(适用于有一定基础者)
- JAVA的OPENGL,JOGL入门例子----碰撞移动的正方体
- java多线程的例子
- Java语言入门 -- 第七章 Java的多线程
- java入门教程:网络通信例子(一)
- 线程进程【重磅出击】 java入门到精通——多线程(上)
- [转]java多线程例子
- java多线程例子