随笔-95  评论-31  文章-10  trackbacks-0


-Object类中有五个关于线程的方法:三个重载的wait()方法和notify()、notifyAll()
问题1:为什么这些方法不定义在Thread类里面作为静态方法使用?而是在Object类里面?

这个问题先放下,先看线程状态图:

new出一个线程后,处于Runnable状态,获得CPU控制权后执行,接着处于Running状态,如果没有控制,正常执行完毕会自动消亡即Dead。
处于Running状态的线程,第一:调用sleep或者join方法或者阻塞IO会进入阻塞状态,一旦释放会自动进入Runnable状态。第二:调用wait方法会使线程处于等待池(是个对象池),一旦调用notify()或者interupt()方法线程会进入锁池(是个对象池),然后就会进入Runnable状态,等待CPU控制权。第三:运行中的线程进入synchronized方法或者synchronized代码段,会进入锁池,并且只有在synchronized里面才能调用wait()方法。

 1public Class MyStack
 2{
 3 private int[] a;
 4 private int MAX_SIZE;
 5 private int count;
 6
 7 public MyStack(){}
 8 public MyStack(int size)
 9{
10   MAX_SIZE=size;
11   a = new int[MAX_SIZE];
12}
 
13
14  public synchronized void push()
15{
16    while(count==MAX_SIZE)
17{
18    try{
19    this.wait();
20    }
catch(InterruptedException e)
21{
22}
   
23}

24    a[count++]=count;
25    System.out.println(Thread.currentThread().getName():"当前线程增加一个数据后:"+count);
26     this.notifyAll();
27}

28public synchronized int pop()
29{
30   while(count==0)
31{   
32try{
33    this.wait();
34   }
catch(InterruptedException e)
35{}
36}
  
37   this.notifyAll();
38   System.out.println(Thread.currentThread().getName():"当前线程减少一个数据后:"+(count-1));
39   return a[--count];
40}

41}

 

 1public Class Producer extends Thread
 2{
 3  private MyStack stack;
 4  public Producer(MyStack stack)
 5{
 6  this.stack= stack;
 7}

 8  @Override
 9  public void run()
10{
11  while(true)
12{
13   stack.push();
         try{
          Thread.sleep(200)
         }catch(Exception e)
        {}
14}

15}

16}

 

public Class Consumer extends Thread
{
  
private MyStack stack;
  
public Consumer(MyStack stack)
{
   
this.stack=stack;
}

  @Override
  
public void run()
{
  
while(true)
{
   stack.pop();
         try{
          Thread.sleep(200)
}catch(Exception e)
        {}

}


}


}


当调用push方法的时候,当前线程锁定this对象,当栈满了,开始调用wait()方法,使生产者线程处于等待池。当消费者线程通知生产者线程继续生产的时候,wait()方法终结,如果使用if条件,并且处于多线程状态(有若干个生产者线程),那么这个时候有可能另外一个处于锁池状态的线程开始执行,那么该线程会生产导致栈满,而这个时候刚执行完wait()方法的线程也开始生产,那么会导致溢出。所以采用while循环,继续判断栈是否满,如果不满,那么执行生产,这个时候绝对不会出现任何问题,因为synchronized该线程获得锁,其余线程无法进入,必定安全。

释放对象的锁:
1、执行完同步代码块,就会释放锁
2、执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放锁,进入对象的等待池。
3、执行同步代码块的过程中,遇到异常而导致线程终止,锁也会释放

不会释放锁:
1、执行了Thread.sleep()方法,当前线程放弃CPU,开始睡眠,但不会释放锁。
2、执行同步代码块的过程中,执行了Thread.yield()方法,当前线程放弃CPU但不会释放锁。

posted on 2011-11-09 22:04 朔望魔刃 阅读(210) 评论(0)  编辑  收藏 所属分类: java

只有注册用户登录后才能发表评论。


网站导航: