package com.bjsxt.thred ;
public class TT implements Runnable {
int b = 100;
public synchronized void m1() throws Exception{
b = 1000;
Thread.sleep(1000);
System.out.println("b = " + b);
}
public synchronized void m2() throws Exception {
Thread.sleep(2500);
b = 2000;
System.out.println(b);
}
public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start();
tt.m2();
System.out.println("a =" + tt.b);
}
}
//为什么这段代码的最后输出是:
//2000
//a =2000
//b = 1000
//关于线程同步的执行先后问题,有点头大啊,哪位大神,帮忙解释一下呢?我怎么感觉b = 1000 应该先打印啊。。
我把程序改动改动,发现一个问题 ,不管谁先输出,a = 2000总是跟第一句话同时打印,总是在第二句打印,这是为什么呢?小弟不才~~!!
public class TT implements Runnable {
int b = 100;
public synchronized void m1() throws Exception{
b = 1000;
Thread.sleep(1000);
System.out.println("b = " + b);
}
public synchronized void m2() throws Exception {
Thread.sleep(2500);
b = 2000;
System.out.println(b);
}
public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start();
tt.m2();
System.out.println("a =" + tt.b);
}
}
//为什么这段代码的最后输出是:
//2000
//a =2000
//b = 1000
//关于线程同步的执行先后问题,有点头大啊,哪位大神,帮忙解释一下呢?我怎么感觉b = 1000 应该先打印啊。。
我把程序改动改动,发现一个问题 ,不管谁先输出,a = 2000总是跟第一句话同时打印,总是在第二句打印,这是为什么呢?小弟不才~~!!
解决方案 »
- 该例子是如何实现的,能否讲解一下
- java 的 string.value() to.String() (String) 这3种强转方式有什么区别啊??
- java中对字符串的简单查找,else语句影响结果,请看代码中的/* */
- (求助)用java写一个图形界面的ftp客户端
- String 怎么才能转成 int 型。
- 如何使写入的记录在文本文件中一个记录占一行?
- 各位GG、JJ,小弟请教一个问题~~~~~~请赐教~~~~谢谢啦
- java多线程问题
- 再次请教!
- 最小的java系统
- 浅析对面向过程软件工程和面向对象软件工程的理解
- The public type MyPanel must be defined in its own file
程序执行的顺序可以从这三句开
t.start();
tt.m2();
System.out.println("a =" + tt.b);下面逐句分析:
t.start();
表示线程启动,但是启动不是代表马上就执行run()里的语句(操作系统决定)
所以:
tt.m2();
得到执行,由于m2是同步方法,所以进入后锁定当前对象this,拿到锁了
m2进入睡眠,这时m1可能已经得到时间片了,开始执行了,由于m1也是
同步方法,所以它必须先拿到锁,但是锁已经被m2先拿到了,所以它必须等待
m2执行完才能够继续执行,故:
首先输出:2000
m2执行完毕,现在有2条路,第一条是m1要执行,第二条是main要继续执行
到底谁先执行,还是操作系统说了算,
如果main先,那么输出:a = 2000 ,然后m1执行输出 b=1000
如果m1先,那么b=1000,m1睡眠,继续main执行,故输出:
a=1000 b=1000
int b = 100; public synchronized void m1() throws Exception {
System.out.println("m1.....");
b = 1000;
Thread.sleep(1000);
System.out.println("b = " + b);
} public synchronized void m2() throws Exception {
System.out.println("m2.....");
Thread.sleep(2500);
b = 2000;
System.out.println(b);
} public void run() {
System.out.println("run.....");
try {
m1();
} catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) throws Exception {
ThreadTest tt = new ThreadTest();
Thread t = new Thread(tt);
t.start();
//tt.run();
tt.m2();
System.out.println("a =" + tt.b);
}
}
好一番研究啊,lz我将你代码加了几句打印语句,大胆猜测其中原理:
首先贴出运行结果m2.....
run.....
2000
m1.....
a =1000
b = 1000
其实从打印结果基本就知道了,问题重点是先运行run()还是m2(),先拿到锁就先执行,因为是锁住整个对象。首先main线程执行栈中必然是t.start()先运行(靠前),但是这里运行的是Thread类的一个实例t的方法,看看Thread类部分源码public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
private native void start0();
public void run() {
if (target != null) {
target.run();
}
}
start()方法里边执行了这么多步,最后还要由JVM去执行run(),跑一个单独线程有这些东西。反观tt.m2()直接调用自己类中方法,虚拟机中就是一两个引用,自然就是先执行m2()了。
PS:打开tt.run();//注释tt.m2();执行结果(先执行run()):
run.....
m1.....
run.....
b = 1000
a =1000
m1.....
b = 1000