线程同步1中解决的是方法appendChar()在不同线程中改变StringBuilder对象而引发的不同步问题。进一步的问题是,如果现在有两个不同的方法A()和B(),他们在不同的线程中改变StringBuilder对象,这样引发的线程不同步该怎样避免?
解决上述问题的一种方法是线程中的沉睡(wait())和唤醒(notify())机制。同一时间要让方法A()和B()中的一个处于唤醒状态,一个处于沉睡状态。一个线程执行完毕,沉睡前唤醒另一个线程,如此往复,以保证线程的同步。
这就涉及到了多线程同步问题中一个很经典的案例——生产者和消费者。生产者把生产出的产品放到容器中,逐渐累积。容器被放满时要停止生产,进入沉睡状态(阻塞队列)。当容器不满时,给生产线程信息,开始生产(阻塞队列→就绪队列)。消费者消耗容器中的产品,如果容器中的产品被耗尽,则进入沉睡状态(阻塞队列),停止消耗。当容器进入新产品时,给消费线程信息,开始消耗(阻塞队列→就绪队列)。
代码示例如下:
public class ProduceAndConsumer { private StringBuilder sb = new StringBuilder(); //生产——添加char public synchronized StringBuilder appendChar(char a,int id){ //先判断容器是否装满 while(sb.length()>=5){//自设定 长度到5为满 try { wait();//进入沉睡状态 } catch (InterruptedException e) {e.printStackTrace();} } sb.append(a); System.out.println(id+",生产了:"+a +" 容器:"+sb); this.notify();//已加入产品,唤醒消费线程(如果沉睡) return sb; } //消费产品——删除char public synchronized char deleteChar(int id){ //判断容器是否已耗尽 while(sb.length()==0){ try{ wait(); }catch(InterruptedException e){e.printStackTrace();} } char cDel = sb.charAt(0); sb.deleteCharAt(0); System.out.println(id+",消费了:"+cDel +" 容器:"+sb); this.notify(); return cDel; } public static void main(String[] args){ ProduceAndConsumer pac = new ProduceAndConsumer(); new Thread(new AppendThread(pac)).start(); new Thread(new DeleteThread(pac)).start(); } } //生产线程 class AppendThread implements Runnable{ ProduceAndConsumer pac; private char c=97; public AppendThread(ProduceAndConsumer pac){ this.pac = pac; } public void run(){ for(int i=0;i<10;i++){ pac.appendChar(c++,i); } } } //消费线程 class DeleteThread implements Runnable{ ProduceAndConsumer pac; public DeleteThread(ProduceAndConsumer pac){ this.pac = pac; } public void run(){ for(int i=0;i<10;i++){ pac.deleteChar(i); } } }
运行结果如下(每次运行的结果可能不同),传入的参数int id只用来打印标号:
结果中,生产线程在id=4处生产e了,容器中变为abcde,容器充满(程序中设定最大长度为5),所以AppendThread线程进入沉睡状态,即进入阻塞队列。此时只运行DeleteThread消费线程。当消费线程在id=0处运行后,删除了a,容器又有了空间。此时又唤醒了AppendThread线程,即从阻塞队列进入就绪队列。由于只启动了两个线程,而且DeleteThread正在运行,所以AppendThread线程在就绪队列中不用等待,可以直接运行。后面的运行结果中,AppendThread线程和DeleteThread线程配合得当,容器中一直装有产品,且不满。两个线程都正常运行。
这样就实现了两个方法A()和B()在不同线程中的同步。
相关推荐
java线程同步java线程同步java线程同步
java线程同步实例,哲学家思考的代码实现,应该是一个比较好的例子
Java多线程同步论文.doc
java多线程同步互斥访问实例,对于初学者或是温故而知新的同道中人都是一个很好的学习资料
本书的新版本展示了如何利用Java线程工具的全部优势,并介绍了JDK 2线程接口中的最新变化。你将学习如何使用线程来提高效率,如何有效地使用它们,以及如何避免常见的错误。本书讨论了死锁、竞态条件以及饥饿等问题...
java线程同步
Java线程(二):线程同步synchronized和volatile 详细讲解Java 同步的原理技术资料
Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的线程 ...
JAVA代码采用线程来实现数据库的主从同步更新
关于线程同步 synchronize,需要牢牢记住的第一点是:线程同步就是线程排队。同步就是排队。线程同步的目的就是避免线程“同步”执行。
操作系统实验 多线程同步与互斥 java编写 可动态创建
java线程同步的例子.doc java线程同步的例子.doc
Java 线程同步调用的使用,以及同步方法的调用!
java 多线程同步方法的实例 java 多线程同步方法的实例 java 多线程同步方法的实例
1.线程同步 2.线程间通信 3.线程挂起、恢复和终止 demo演示
里面讲述了关于java线程同步的信息·······
Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的...
Java多线程同步.pdf
Java多线程同步具体实例.doc
java多线程同步分析java多线程同步分java多线程同步分析析java多线程同步分析java多线程同步分析