通过这个例题学到了很多,记录下来便于以后常看,<线程通信>
/*
* 写两个线程,一个线程打印1-52,另一个线程打印字母A-Z。打印 顺序为12A34B56C……5152Z>
*/
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Object obj = new Object();
Shuzi s = new Shuzi(obj);
Zimu z = new Zimu(obj);
Thread th1 = new Thread(s);
Thread th2 = new Thread(z);
th1.start();//数字的线程先运行,数字先执行
th2.start();
/*th2.start();
* th1.start();字母的线程先运行,则先执行字母
*/
}
}
class Shuzi implements Runnable{
private Object obj;//声明一个类的引用
public Shuzi(Object obj){
this.obj = obj; //通过构造器将共享的资源-->对象传进来
}
@Override
public void run() {
synchronized(obj){//给共享资源上锁
for(int i = 1;i < 53;i++ ){
System.out.println(i);
if(i % 2 == 0){
obj.notifyAll();//唤醒其他线程
try {
obj.wait();//等待并释放锁
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
class Zimu implements Runnable{
private Object obj;
public Zimu(Object obj){
this.obj = obj;
}
@Override
public void run() {
synchronized(obj){
for(int i = 0;i < 26;i++ ){
System.out.println((char)(i+'A'));
obj.notifyAll();//唤醒其他线程
try {
obj.wait();//释放锁等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
这是线程间的通信的一个很有代表性的例子。过程如下:
1、创建两个线程实现Runnable接口重写run方法,一个用于打印数字,一个用于打印字母。
2、创建一个测试类,在测试类中创建一个Object类的对象(作为两个线程的共享资源,以便实现线程间的通信),通过各类的构造方法传递过去。
3、在两个类的run方法中都要用synchronized保证同步,即加锁。
4、在数字类中用for循环每打印两个数字就唤醒其他线程,释放锁,进入阻塞状态。
在字母类中每打印一个字母就唤醒其他线程,释放锁,进入阻塞状态。
在写这个程序的时候有几点要注意的地方:
1、两个线程要使用同一个资源才需相互通信,所以在测试类中创建共享资源,并通过构造方法分别传到各线程类中。
2、两个线程哪个先运行(执行start())哪个就先获得资源并执行
3、在run方法体内写进程间的通信wait()和notifyall()时,一定要先写notifyall()再写wait()。
原因:当你先写wait()时,本进程也进入休眠状态,再写notifyall()唤醒所有线程时本线程以及其他线程被一块唤醒,竞争同一个资源,就会造成死锁。 所以一定要先唤醒其他线程,再让本线程阻塞!
分享一些技术学习视频教程 https://pan.baidu.com/s/13dbR69NLIEyP1tQyRTl4xw
联系客服