参考资料
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);
}
}
}