Java中线程的高级应用
2010-10-05 01:23:09 来源:WEB开发网3、线程间同步通讯---线程的阻塞:
多线程除互斥外,在某些应用场合下还应考虑线程间同步通讯----线程的阻塞(一个线程等待另外一个线程的执行并根据该线程的执行结果自己再执行,也即阻塞指的是暂停一个线程的执行以等待某个条件发生,如某资源就绪等)。
因为在任意时刻所要求的资源不一定已经准备好了被访问,反过来,同一时刻准备好了的资源也可能不止一个。为了解决这种情况下的访问控制问题,Java 引入了对线程间同步通讯----线程的阻塞机制的支持。
线程在继续执行前需要等待一个条件时,仅有 synchronized 关键字是不够的。虽然 synchronized 关键字阻止并发更新一个对象,但它没有实现线程间同步通讯。
Object 类为此提供了三个函数:wait()、notify() 和 notifyAll()。
(1)线程同步应用的场合:
在"生产者---消费者"式的问题中。
(2)生产者---消费者的问题:
生产者每生产出一件产品(创建出数据),消费者都能及时地消费它(使用数据),不能提前或落后;否则将不匹配(消费者获取得数据将不是生产者产生的数据)。
(3)实现的手段:
利用 wait()(释放同步锁,进入等待队列)、notify()(唤醒等待队列中的第一个线程,并把它移人同步锁申请队列)及notifyAll()方法(它们只能在synchronized同步方法中被调用)。
(4)等待—通知机制:
通过使用wait(),一个线程可以等待对象里的一些条件的改变,而通过notify()和notifyAll(),一个线程也可以通知等待对象条件的所有线程,告诉它们条件已经改变,可以继续执行。通常的一种情况是一个线程产生对象的数据,而另一个线程使用对象的数据。
(5)实例1:(线程与进程之间通讯)
问题:实时跟踪显示用户移动鼠标时的落点位置(将用户移动鼠标时的落点位置作为生产者传递给线程,由线程显示出鼠标坐标位置)。
import java.awt.*; import java.applet.*; public class ThreadCom extends Applet implements Runnable { Thread myThread; List ConsumeList=new List(),ProduceList=new List(); int x=0,y=0; private boolean isAvailable=false; //定义一个标置变量 public void init() //定义两个List控件并重置其大小 { ConsumeList.resize(size().width/4,size().height); ProduceList.resize(size().width/4,size().height); setLayout(new BorderLayout());//定位两个List控件的位置及布局 add("East",ConsumeList); add("West",ProduceList); if(myThread ==null) { myThread=new Thread(this); myThread.start(); //产生并启动一个线程 } ProduceList.addItem("Produce"+"("+x+","+y+")"); } public synchronized void run() //同步方法 线程 ! { while(myThread ==Thread.currentThread()) { //在List控件中显示出鼠标坐标位置值 ConsumeList.addItem("Consume"+"("+x+","+y+")"); while(isAvailable ==false) {//让线程处于等待状态(暂停)直到被notify() 或notifyAll()唤醒因wait()定义有异常,所以应捕获它 try { wait(); } catch(Exception e) { System.out.println(e); } } isAvailable=false; //设置消费数字完毕标置 notify(); //释放监视器 } } public synchronized boolean mouseMove(Event evt, int x, int y) {//鼠标移动的响应函数 while(isAvailable ==true) //等待消费者获得新的数字(等待消费者释放监视器) { try { wait(); } catch(InterruptedException e) { } } isAvailable=true; //设置生产数字完毕标置 notify(); //释放监视器以唤醒处于等待状态的线程 this.x=x; //获得鼠标位置 进程 this.y=y; ProduceList.addItem("Produce"+"("+x+","+y+")"); return true; } /* public void run() { while(myThread ==Thread.currentThread()) { ConsumeList.addItem("Consume"+"("+x+","+y+")"); } } public boolean mouseMove(Event evt, int x, int y) { this.x=x; this.y=y; ProduceList.addItem("Produce"+"("+x+","+y+")"); return true; } */ }
程序执行结果有错,生产者(移动鼠标)与消费者(线程)未同步,不匹配,改为同步方法。
更多精彩
赞助商链接