wait()和notify()

  • 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
  • 如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
  • 如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
分析wait方法:
1) 哪个线程调用了wait方法
2) 调用的是哪个对象的wait方法
3) 该线程继续执行的条件: 调用wait方法的那个对象在其他线程中调用了他的notify方法

注意:
wait和notify必须用在同步锁内部, 脱离同步锁不能使用
wait方法和sleep不同, sleep是使当前线程休眠但是继续持有锁, 而wait是会释放当前锁, 而wait执行结束继续向下执行时需要重新获得对象锁才可以

使用wait的目的并不是为了释放当前线程占有对象的控制权, 而是为了等待当前线程继续执行时所需的资源, 所以wait方法所在的同步锁由需要哪个对象来获取资源决定, 如下1是需要通过自身获取资源, 则在自身的对象锁中使用wait方法, 如下2是需要stack对象获取资源, 则在stack对象锁中使用wait方法

1.在自身线程中释放占有的自身对象
  @Override  
    public void run() {  
        while (!isShutdown) {  
            if (target != null) {  
                target.run();  
            }  
            try {  
            	//空闲线程对象放入池中
                pool.putThread(this); 
                //System.out.println(pool.getThreadCount());
                // 线程执行完任务,会在wait处阻塞,直到 setTarget或者 shutdown 调用notifyAll  
                synchronized (this) {  
                    wait();  
                }  
            } catch (InterruptedException e) {  
  
            }  
        }  
    }  
  
    // 每当设置任务或关闭时会唤醒run方法  
     public synchronized void setTarget(Runnable r) {  
        this.target = r;  
        notifyAll();  
    } 

2.在自身线程中释放占有的其他对象
public T getInstance() {
		T t = null;
		synchronized (stack) {
			if (stack.size() > 0) {
				t = stack.pop();
				usedSize++;
			} else if (usedSize < maxSize) {
				try {
					t = (T) Class.forName(classpath).newInstance();
					
					usedSize++;
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			// 当前要获取对象的线程等待,等待stack中有对象归还
			else {
				try {
					System.out.println("dengdai");
					stack.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				// 注意这里如果使用t = stack.pop()在线程调用多的情况下可能报错
				t = getInstance();
			}
		}

		return t;
	}

	public void returnInstance(T t) {
		//对象归还时是否要对对象做初始化
		synchronized(stack) {
			stack.push(t);
			usedSize--;
			stack.notify();
		}
	}


posted @ 2017-08-14 16:32  車輪の唄  阅读(24)  评论(0)    收藏  举报  来源