java事件队列代码 java事件处理的过程( 二 )


Java的多线程-线程间的通信2009-08-25 21:58
1. 线程的几种状态
线程有四种状态,任何一个线程肯定处于这四种状态中的一种:
1) 产生(New):线程对象已经产生 , 但尚未被启动 , 所以无法执行 。如通过new产生了一个线程对象后没对它调用start()函数之前 。
2) 可执行(Runnable):每个支持多线程的系统都有一个排程器,排程器会从线程池中选择一个线程并启动它 。当一个线程处于可执行状态时,表示它可能正处于线程池中等待排排程器启动它;也可能它已正在执行 。如执行了一个线程对象的start()方法后 , 线程就处于可执行状态,但显而易见的是此时线程不一定正在执行中 。
3) 死亡(Dead):当一个线程正常结束,它便处于死亡状态 。如一个线程的run()函数执行完毕后线程就进入死亡状态 。
4) 停滞(Blocked):当一个线程处于停滞状态时,系统排程器就会忽略它,不对它进行排程 。当处于停滞状态的线程重新回到可执行状态时 , 它有可能重新执行 。如通过对一个线程调用wait()函数后,线程就进入停滞状态 , 只有当两次对该线程调用notify或notifyAll后它才能两次回到可执行状态 。
2. class Thread下的常用函数函数
2.1 suspend()、resume()
1) 通过suspend()函数,可使线程进入停滞状态 。通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回可执行状态 。
2) 当调用suspend()函数后,线程不会释放它的“锁标志” 。
例11:
class TestThreadMethod extends Thread{
public static int shareVar = 0;
public TestThreadMethod(String name){
super(name);
}
public synchronized void run(){
if(shareVar==0){
for(int i=0; i5; i++){
shareVar++;
if(shareVar==5){
this.suspend(); //(1)
}}}
else{
System.out.print(Thread.currentThread().getName());
System.out.println(" shareVar = " + shareVar);
this.resume(); //(2)
}}
}
public class TestThread{
public static void main(String[] args){
TestThreadMethod t1 = new TestThreadMethod("t1");
TestThreadMethod t2 = new TestThreadMethod("t2");
t1.start(); //(5)
//t1.start(); //(3)
t2.start(); //(4)
}}
运行结果为:
t2 shareVar = 5
i. 当代码(5)的t1所产生的线程运行到代码(1)处时,该线程进入停滞状态 。然后排程器从线程池中唤起代码(4)的t2所产生的线程,此时shareVar值不为0,所以执行else中的语句 。
ii. 也许你会问,那执行代码(2)后为什么不会使t1进入可执行状态呢?正如前面所说,t1和t2是两个不同对象的线程 , 而代码(1)和(2)都只对当前对象进行操作 , 所以t1所产生的线程执行代码(1)的结果是对象t1的当前线程进入停滞状态;而t2所产生的线程执行代码(2)的结果是把对象t2中的所有处于停滞状态的线程调回到可执行状态 。
iii. 那现在把代码(4)注释掉,并去掉代码(3)的注释,是不是就能使t1重新回到可执行状态呢?运行结果是什么也不输出 。为什么会这样呢?也许你会认为,当代码(5)所产生的线程执行到代码(1)时,它进入停滞状态;而代码(3)所产生的线程和代码(5)所产生的线程是属于同一个对象的,那么就当代码(3)所产生的线程执行到代码(2)时,就可使代码(5)所产生的线程执行回到可执行状态 。但是要清楚,suspend()函数只是让当前线程进入停滞状态,但并不释放当前线程所获得的“锁标志” 。所以当代码(5)所产生的线程进入停滞状态时,代码(3)所产生的线程仍不能启动 , 因为当前对象的“锁标志”仍被代码(5)所产生的线程占有 。

推荐阅读