java 多线程实现生产者消费者模型
来源:互联网 发布:linux 浏览网页 编辑:程序博客网 时间:2024/06/05 08:40
1、在线程操作中有一个经典的案例程序,即生产者和消费者问题,生产者不断生产,消费者不断取走生产者生产的产品。程序的基本实现如下:
package Thread;/** * 信息类 */class Info { private String name = "张三"; private String content = "产品经理"; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; }}/** * 生产者 */class Producer implements Runnable{ private Info info = null; public Producer(Info info){ this.info = info; } @Override public void run() { // TODO Auto-generated method stub boolean flag = true; for(int i=0;i<50;i++){ if(flag){ this.info.setName("张三"); try{ Thread.sleep(90); }catch(Exception e){ e.printStackTrace(); } this.info.setContent("产品经理"); flag = false; }else{ this.info.setName("李四"); try{ Thread.sleep(90); }catch(Exception e){ e.printStackTrace(); } this.info.setContent("程序员"); flag = true; } } }}class Consumer implements Runnable{ private Info info = null; public Consumer(Info info){ this.info = info; } @Override public void run() { for(int i=0;i<50;i++){ try{ Thread.sleep(100); }catch(Exception e){ e.printStackTrace(); } System.out.println(this.info.getName()+"-->"+this.info.getContent()); } }}public class ThreadCaseDemo01 { public static void main(String[] args) { Info i = new Info(); Producer pro = new Producer(i); Consumer con = new Consumer(i); new Thread(pro).start(); new Thread(con).start(); }}
2、此时会出现下面两个问题:
(1)假设生产者线程刚向数据存储空间添加了信息的名称,还没有加入信息的内容,程序就切换到了消费者线程,消费者线程把信息的名称和上一个信息的内容联系到一起。
(2)生产者放了若干次的数据,消费者才开始取数据,或者是,消费者取完一个数据后,还没等到生产者放入新的数据,又重复取出已取过的数据。
3、问题解决
(1)加入同步
要为操作加入同步,则可以通过定义同步方法的方式完成,即将设置名称和姓名定义成一个同步方法,代码如下:
package Thread;/** * 信息类 */class Info { private String name = "张三"; private String content = "产品经理"; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public synchronized void set(String name,String content){ this.setName(name); try { Thread.sleep(90); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.setContent(content); } public synchronized void get(){ try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(this.getName()+"-->"+this.getContent()); }}/** * 生产者 */class Producer implements Runnable{ private Info info = null; public Producer(Info info){ this.info = info; } @Override public void run() { // TODO Auto-generated method stub boolean flag = true; for(int i=0;i<50;i++){ if(flag){ this.info.set("张三", "产品经理"); flag = false; }else{ this.info.set("李四", "程序员"); flag = true; } } }}/** * 消费者 */class Consumer implements Runnable{ private Info info = null; public Consumer(Info info){ this.info = info; } @Override public void run() { for(int i=0;i<50;i++){ try{ Thread.sleep(100); }catch(Exception e){ e.printStackTrace(); } this.info.get(); } }}public class ThreadCaseDemo01 { public static void main(String[] args) { Info i = new Info(); Producer pro = new Producer(i); Consumer con = new Consumer(i); new Thread(pro).start(); new Thread(con).start(); }}
程序的运行结果部分截图如下:
从程序的运行结果中可以发现,信息错乱的问题已经解决了,但是依然存在重复读取的问题,既然有重复读取,则肯定会有重复设置的问题,那么对于这样的问题该如何解决呢?此时,就要用Object类来帮忙了
(2)加入等待与唤醒
修改Info类,代码如下:
/** * 信息类 */class Info { private String name = "张三"; private String content = "产品经理"; private boolean flag = false; //设置标志位 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public synchronized void set(String name,String content){ if(!flag){ try{ super.wait(); //等待消费者取走 }catch(Exception e){ e.printStackTrace(); } } this.setName(name); try { Thread.sleep(90); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.setContent(content); flag = false; super.notify(); //唤醒等待线程 } public synchronized void get(){ if(flag){ try { super.wait(); //等待生产者生产 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(this.getName()+"-->"+this.getContent()); flag = true; super.notify(); //唤醒等待线程 }}
此时程序运行结果如下图:
从程序的运行结果可以清楚的发现,生产者每生产一个就要等待消费者取走,消费者每取走一个就要等待生产者生产,这样就避免了重复生产和重复取走的问题。至此问题得到解决,最终代码如下:
package Thread;/** * 信息类 */class Info { private String name = "张三"; private String content = "产品经理"; private boolean flag = false; //设置标志位 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public synchronized void set(String name,String content){ if(!flag){ try{ super.wait(); //等待消费者取走 }catch(Exception e){ e.printStackTrace(); } } this.setName(name); try { Thread.sleep(90); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.setContent(content); flag = false; super.notify(); //唤醒等待线程 } public synchronized void get(){ if(flag){ try { super.wait(); //等待生产者生产 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(this.getName()+"-->"+this.getContent()); flag = true; super.notify(); //唤醒等待线程 }}/** * 生产者 */class Producer implements Runnable{ private Info info = null; public Producer(Info info){ this.info = info; } @Override public void run() { // TODO Auto-generated method stub boolean flag = true; for(int i=0;i<50;i++){ if(flag){ this.info.set("张三", "产品经理"); flag = false; }else{ this.info.set("李四", "程序员"); flag = true; } } }}/** * 消费者 */class Consumer implements Runnable{ private Info info = null; public Consumer(Info info){ this.info = info; } @Override public void run() { for(int i=0;i<50;i++){ try{ Thread.sleep(100); }catch(Exception e){ e.printStackTrace(); } this.info.get(); } }}public class ThreadCaseDemo01 { public static void main(String[] args) { Info i = new Info(); Producer pro = new Producer(i); Consumer con = new Consumer(i); new Thread(pro).start(); new Thread(con).start(); }}
0 0
- JAVA实现多线程生产者消费者模型
- Java实现生产者消费者模型:多线程+BlockingQueue
- java 多线程实现生产者消费者模型
- java多线程生产者、消费者模型
- Java多线程 -- 生产者消费者模型
- Java 多线程:生产者消费者模型
- Java 多线程:生产者消费者模型
- Java多线程--生产者消费者模型(Semaphore实现)
- 2、java多线程--利用BlockingQueue实现生产者消费者模型
- java实现生产者消费者模型
- Java实现生产者-消费者模型
- Java---实现生产者消费者模型
- Java实现生产者消费者模型
- 生产者消费者Java多线程实现
- Java多线程实现,生产者消费者
- Android平台多线程实现生产者-消费者模型
- 多线程模拟实现生产者/消费者模型
- 多线程模拟实现生产者/消费者模型
- 开启reuse_port让Tengine性能提升3倍
- 虚拟内存之TLB加速地址翻译
- 虚拟存储器之地址翻译
- 秒杀系统架构分析与实战
- TCP的三次握手和四次撒手
- java 多线程实现生产者消费者模型
- STM32_SPI_笔记
- iOS学习 UITableViewCell 三种定制方法
- 虚拟存储器作为存储管理工具
- Nginx + CGI/FastCGI + C/Cpp
- FTP服务器的安装,配置,虚拟用户的创建
- 在Linux CentOS 6.5上安装python2.7.9
- Huge Page 是否是拯救性能的万能良药?
- 代码重构思考