Java之线程(synchronized,wait(),notify(),notifyAll())

参考资料
Java多线程入门大全(适用于有一定基础者)
http://www.chinaitpower.com/A/2002-04-09/19260.html
Java多线程sleep(),join(),interrupt(),wait(),notify()
http://www.blogjava.net/fhtdy2004/archive/2009/06/08/280728.html
JAVA多线程suspend()、resume()和wait()、notify()的区别
http://luckyapple.iteye.com/blog/457298
总结如下:
1.有synchronized的地方不一定有wait,notify,notifyAll,
2.有wait,notify的地方必有synchronized.这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法,而且,这两个方法都和对象锁有关,有锁的地方,必有synchronized.
3.如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是current thread了.
4 推荐使用notifyAll.

一 synchronized的4种用法
1 方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前.即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.
public synchronized void synMethod() {
        //方法体
 }

2 对某一代码块使用synchronized后跟括号,括号里是变量,一次只有一个线程进入该代码块
public int synMethod(int a1){
        synchronized(a1) {
          //一次只能有一个线程进入
        }
}

3 synchronized后面括号里是一对象,此时,线程获得的是对象锁
public class MyThread implements Runnable {

       public static void main(String args[]) {
                MyThread mt = new MyThread();
                Thread t1 = new Thread(mt, "t1");
                Thread t2 = new Thread(mt, "t2");               
                t1.start();
                t2.start();              
        }

       public void run() {
                synchronized (this) {
                  System.out.println(Thread.currentThread().getName());
              }
       }
 } 

4 synchronized后面括号里是类,只要线程进入,则该类中所有操作不能进行,包括静态变量和静态方法,实际上,对于含有静态方法和静态变量的代码块的同步,我们通常用4来加锁
synchronized(A.class) {
  //
}

示例如下:
public class MyRunnable implements Runnable {

	@SuppressWarnings("deprecation")
	@Override
	public void run() {		
		System.out.println("咫尺天涯的第一个线程(Runnable)启动了。。。");
		synchronized (this) {
			System.out.println("开始执行任务了...");
			//模仿一个任务所要的时间
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("任务完成了,我来叫醒你好吗?");
			//推荐使用这种方式来唤醒线程上等待的对象
			notifyAll();			
		}
	}
}

public class Main {
	
	public static void main(String[] args) {
		
		MyRunnable myRunnable = new MyRunnable();		
		Thread runnable = new Thread(myRunnable,"咫尺天涯(Runnable)");
		runnable.start();
		
		synchronized (runnable) {
			
			try {
                System.out.println("快点完成任务呀,等待你来唤醒我。。。");
                //当前线程A等待
                runnable.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }  
            
            System.out.println("你叫醒我了...");	
	   }		
	}
}

输出结果如下:
快点完成任务呀,等待你来唤醒我。。。
咫尺天涯的第一个线程(Runnable)启动了。。。
开始执行任务了...
任务完成了,我来叫醒你好吗?
你叫醒我了...

网上有个示例不错,它是等待一个计算结果,如下:
/**
* 计算1+2+3 ... +100的和
*
* @author leizhimin 2008-9-15 13:20:49
*/
public class ThreadB extends Thread {
    int total;

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 101; i++) {
                total += i;
            }
            //(完成计算了)唤醒在此对象监视器上等待的单个线程,在本例中线程A被唤醒
            notify();
        }
    }
}

/**
* 计算输出其他线程锁计算的数据
*
* @author leizhimin 2008-9-15 13:20:38
*/
public class ThreadA {
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        //启动计算线程
        b.start();
        //线程A拥有b对象上的锁。线程为了调用wait()或notify()方法,该线程必须是那个对象锁的拥有者
        synchronized (b) {
            try {
                System.out.println("等待对象b完成计算。。。");
                //当前线程A等待
                b.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("b对象计算的总和是:" + b.total);
        }
    }
}

你可能感兴趣的:(java,synchronized,notifyAll,wait,notify)