通过这个例题学到了很多,记录下来便于以后常看,<线程通信> /* * 写两个线程,一个线程打印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
|