/**
* 2017年6月18日
* 功能:线程通信
* 题目描述:编写两个线程,一个线程打印1-52,另外一个进程打印字母A-Z,
* 打印的顺序为12A34B56C...5152Z
* 字符 ASCII
* 0-9 48-57
* A-Z 65-90
* a-z 97-122
*/
public class Test {
public static void main(String[] args) {
Object object=new Object();
Runnable runnable1 = new ComsumerThread(object);
Runnable runnable2 = new ProducerThread(object);
Thread thread1 = new Thread(runnable1);
Thread thread2 = new Thread(runnable2);
thread1.start();
thread2.start();
}
}
// 打印数字线程类
class ComsumerThread implements Runnable {
private Object object;
public ComsumerThread(Object object) {
this.object=object;
}
@Override
public void run() {
synchronized(object){
for (int i = 1; i < 53; i++) {
System.out.print(i);
if(i%2==0){
object.notifyAll();
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
// 打印字母线程类
class ProducerThread implements Runnable {
private Object object;
public ProducerThread(Object object) {
this.object=object;
}
@Override
public void run() {
synchronized(object){
for (int i = 65; i <= 90; i++) {
System.out.print((char) i);
object.notifyAll();
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
这是线程间的通信的一个很有代表性的例子。过程如下:
1、创建两个线程实现Runnable接口重写run方法,一个用于打印数字,一个用于打印字母。
2、创建一个测试类,在测试类中创建一个Object类的对象(作为两个线程的共享资源,以便实现线程间的通信),通过各类的构造方法传递过去。
3、在两个类的run方法中都要用synchronized保证同步,即加锁。
4、在数字类中用for循环每打印两个数字就唤醒其他线程,释放锁,进入阻塞状态。
在字母类中每打印一个字母就唤醒其他线程,释放锁,进入阻塞状态。
在写这个程序的时候有几点要注意的地方:
1、两个线程要使用同一个资源才需相互通信,所以在测试类中创建共享资源,并通过构造方法分别传到各线程类中。
2、两个线程哪个先运行(执行start())哪个就先获得资源并执行
3、在run方法体内写进程间的通信wait()和notifyall()时,一定要先写notifyall()再写wait()。
原因:当你先写wait()时,本进程也进入休眠状态,再写notifyall()唤醒所有线程时本线程以及其他线程被一块唤醒,竞争同一个资源,就会造成死锁。
所以一定要先唤醒其他线程,再让本线程阻塞!
参考:http://blog.csdn.net/wallance111/article/details/50864071
2017-6-18