之前对线程并发的理解不够深刻,写一个简单案例体会一下
如题
/**
* sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,
* 给执行机会给其他线程,但是监控 状态依然保持,到时后会自动恢复。
* 调用 sleep 不会释放对象锁。wait 是 Object 类的方法,对此对象
* 调用 wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,
* 只有针对此对象发出 notify 方法(或 notifyAll)后本线程才进入对
* 象锁定池准备获得对 象锁进入运行状态。
*
* sleep:导致此线程暂停执行指定时间;
stop:这个方法将终止所有未结束的方法,包括 run 方法;
wait:当前正在被服务的线程需要睡一会,醒来后继续被服务。
* @author cheng
*
*/
public class Test02 {
public static void main(String args[]) throws InterruptedException {
Thread mThread = Thread.currentThread();
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(250);//1. 这句话注释掉和不注释掉的区别,或者更改sleep里面时间的区别
} catch (InterruptedException e) {e.printStackTrace();
}
pong();
}
};
t.start();//换成t.run(),观察不同一般在笔试题中是陷阱,混淆start
mThread.sleep(250);//2. 这句话注释掉和不注释掉的区别,或者更改sleep里面时间的区别
System.out.print("ping");
}
static void pong() {
System.out.print("pong");
}
}
分析:
情形一:如果把注释1(下文都用1)位置和注释2(下文都用2)位置的代码注释掉,那么输出为“pingpong”,首先从main方法入口顺序执行代码,当线程t被启动时,由于sleep方法都被注释掉了,main方法线程(mthread)和t线程(t)不会存在暂停并给其他线程让出cpu时间这一说。那么在t被启动瞬间,由于mthread还占用这cpu时间,所以会将后面的代码执行完成后输出ping,然后mthread让出cpu时间给t,t执行pong,最终输出pingpong(还有一种解释是mthread的优先级要大于t的优先级,不过应该不正确,毕竟mhread从头到尾如果没有sleep,那么就在一直占用cpu时间不会让给t。如果线程除了sleep,wait,stop方法外还有别的途径能自主放弃cpu时间。那么线程优先级的解释就是正确的,这是一些猜想,希望有人能给出认证。)
情形二:如果把1的代码注释掉,那么显然mthread会进入暂停,会让cpu时间给t,那么t执行输出pong。t线程完成任务被杀死,mthread接收cpu时间执行ping,最终结果输出pongping
情形三:如果1,2处代码都保留,并且里面的时间都写成250毫秒的话,那么有几率输出pingpong,也有几率输出pongping。
我们再从main接口跟着mthread顺序执行main方法内部的代码,当t.start()后,t被启动,这时候mthread进入暂停,然后cpu时间会分配给t,执行t内的run方法,然后t也被暂停。虽然从暂停上来看,mthread和t存在先后,mthread再前,但是这两个线程的暂停方法之间的时间可以忽略不计,为无穷小。那么从这方面分析,两个线程会同时醒来,这时候就看cpu给哪个线程分配时间了,如果是mthread那么显然输出pingpong,如果是t,显然输出pongping