Java多线程-生产者和消费者
2017-02-09 17:28
323 查看
标签(空格分隔): java thread
简介:
随着操作系统的不断更新迭代,多线程编程已经变的十分常见,java虚拟机的多线程一般也是建立在操作系统本地native线程之上的,从而不必自己管理线程间的切换,直接交由本机操作系统进行调度和管理。对于java程序来说,它是运行在虚拟机上的,由于线程间很多资源都是共享的,比如全局数据等等,因此,线程间的同步也就不是那么复杂的。java也提供了许多实现线程同步的方法,我们这里主要分析wait和notify。
问题:
在一个盒子里,能放置一定数量的物体A,同一时间只能准许一个人往箱子里放物体或者一个人从盒子中取出物品。当盒子满了,再往里面放物体的人需要等待。当盒子空了,从盒子中取出物品的人需要等待。
这就是一个典型的生产者和消费者模型,下面在代码的基础上模拟这个过程。
1. 盒子对象
DataManger展示了盒子这个模型,这里需要理解wait和notify以及notifyAll这几个方法。
2.生产者模型
3.消费者模型
Client端代码
总结:
整体结构来说是比较简单的,所有生产者Producer和所有消费者Consumer共享同一个盒子DataManager。同时对盒子进行存取操作。对于上述代码,应该重点理解wait、notify以及notifyAll它们作用的对象,它们三者必须在同步块中使用,同时理解wait会释放对象锁,这点和sleep有区别,而被唤醒后又会重新持有对象锁,这个是线程同步的关键,也是理解这些代码的关键。当然java还有许多api提供了线程同步的方法,比如锁机制,其实两者在原理上是大同小异,都是基于本机操作系统的线程同步机制。
简介:
随着操作系统的不断更新迭代,多线程编程已经变的十分常见,java虚拟机的多线程一般也是建立在操作系统本地native线程之上的,从而不必自己管理线程间的切换,直接交由本机操作系统进行调度和管理。对于java程序来说,它是运行在虚拟机上的,由于线程间很多资源都是共享的,比如全局数据等等,因此,线程间的同步也就不是那么复杂的。java也提供了许多实现线程同步的方法,我们这里主要分析wait和notify。
问题:
在一个盒子里,能放置一定数量的物体A,同一时间只能准许一个人往箱子里放物体或者一个人从盒子中取出物品。当盒子满了,再往里面放物体的人需要等待。当盒子空了,从盒子中取出物品的人需要等待。
这就是一个典型的生产者和消费者模型,下面在代码的基础上模拟这个过程。
1. 盒子对象
public class DataManager { private static final int LIMIT = 20; private List<String> datas = new ArrayList<>(); public synchronized void put( String data ) { while ( datas.size() == LIMIT ) { // size limit, need wait. try { // 处于wait等待的线程会暂时释放锁,当其被唤醒时,会重新获得锁 wait(); } catch ( InterruptedException e ) { e.printStackTrace(); } // 线程被唤醒后,重新检查条件 } datas.add( data ); // 唤醒所有等待的线程 notifyAll(); } public synchronized String get() { while ( datas.size() == 0 ) { // datas is empty, need wait. try { wait(); } catch ( InterruptedException e ) { e.printStackTrace(); } } String data = datas.get( 0 ); datas.remove( 0 ); notifyAll(); return data; } }
DataManger展示了盒子这个模型,这里需要理解wait和notify以及notifyAll这几个方法。
2.生产者模型
public class Producer implements Runnable { static int count = 0; private DataManager mDataManager; public Producer( DataManager dataManager ) { mDataManager = dataManager; } @Override public void run() { while ( true ) { try { sleep( 100 ); } catch ( InterruptedException e ) { e.printStackTrace(); } String data = "data - " + count++; mDataManager.put( data ); System.out.println( "Producer " + Thread.currentThread().getName() + ", put -> " + data ); } } }
3.消费者模型
public class Consumer implements Runnable { private DataManager mDataManager; public Consumer( DataManager dataManager ) { mDataManager = dataManager; } @Override public void run() { while ( true ) { try { sleep( 100 ); } catch ( InterruptedException e ) { e.printStackTrace(); } String data = mDataManager.get(); System.out.println( "Consumer " + Thread.currentThread().getName() + ", get -> " + data ); } } }
Client端代码
public class Client { public static void main( String[] args ) { DataManager dataManager = new DataManager(); for ( int i = 0; i < 20; i++ ) { new Thread( new Producer( dataManager ) ).start(); new Thread( new Consumer( dataManager ) ).start(); } } }
总结:
整体结构来说是比较简单的,所有生产者Producer和所有消费者Consumer共享同一个盒子DataManager。同时对盒子进行存取操作。对于上述代码,应该重点理解wait、notify以及notifyAll它们作用的对象,它们三者必须在同步块中使用,同时理解wait会释放对象锁,这点和sleep有区别,而被唤醒后又会重新持有对象锁,这个是线程同步的关键,也是理解这些代码的关键。当然java还有许多api提供了线程同步的方法,比如锁机制,其实两者在原理上是大同小异,都是基于本机操作系统的线程同步机制。
相关文章推荐
- 由生产者/消费者问题看JAVA多线程
- java 用多线程实现多生产者和多消费者模式
- java多线程 生产者 消费者 问题 。。。
- java多线程总结六:经典生产者消费者问题实现
- java多线程总结六:经典生产者消费者问题实现
- 基于Java多线程机制的生产者-消费者模型模拟
- 用JAVA中的多线程示例生产者和消费者问题
- java多线程 生产者 消费者 问题 。。。
- java 多线程 生产者消费者
- JAVA多线程-生产者与消费者当线程多时发生死锁的解决方法
- java 多线程之 wait(),notify(),notifyAll()以及经典的生产者消费者模型
- 由生产者/消费者问题看JAVA多线程
- java多线程 消费者-生产者
- 回顾生产者/消费者问题下产生的java多线程(一)
- java多线程之生产者与消费者问题的简单模拟
- JAVA多线程实例(生产者与消费者问题)
- JAVA多线程模拟生产者与消费者_实例
- java多线程 消费者-生产者
- java多线程应用——生产者消费者
- 回顾生产者/消费者问题下产生的java多线程(二)