1、线程通信的必要性
多线程不仅共享资源,而且相互牵制向前运行。
2、线程通信的方法(都是在Object中定义)
3个方法:
1) wait() 可运行转入阻塞状态,放锁
2) notify() 阻塞转入可运行状态,获得锁
3) notifyAll() 所有调用wait方法而被挂起的线程重新启动,有个条件:wait与notifyAll必须是属于同一个对象
必须在同步方法或同步代码块中使用
3、共享资源类(仓库)
注:共享资源(产品),牵制信息(产品有无)
package com.ljb.app.communication; /** * 共享资源类 * @author LJB * @version 2015年3月11日 */ public class ShareData { // 产品 private char c; // 牵制信息(产品有无,开始时仓库中没有产品) private boolean isProduced = false; /* * 放产品(生产产品) */ public synchronized void putShareChar (char c) { // 如果消费者还没有消费或者仓库中有产品,则生产者等待 if (isProduced) { System.out.println("消费者还未消费,因此生产者停止生产。"); try { wait();// 生产者等待 } catch (InterruptedException e) { e.printStackTrace(); } } // 仓库中放入生产的产品 this.c = c; // 改变信号量(有产品) isProduced = true; // 通知消费者消费 notify(); System.out.println("生产者生产了产品" + c + ",通知消费者消费..."); } /* * 取产品(消费产品) */ public synchronized char getShareChar () { // 如果生产者还未生产或者仓库中没有产品,则消费者等待 if (!isProduced) { System.out.println("生产者还未生产,因此消费者停止消费。"); try { wait();// 消费者等待 } catch (InterruptedException e) { e.printStackTrace(); } } // 改变信号量(没有产品或者消费了该产品) isProduced = false; // 通知生产者生产 notify(); System.out.println("消费者消费了产品" + c + ",通知生产者生产..."); return this.c; } }
4、生产者线程
package com.ljb.app.communication; /** * 生产者线程,每隔一段时间生产一个产品 * @author LJB * @version 2015年3月11日 */ public class Producer extends Thread{ // 共享资源对象 private ShareData s; // 有参构造方法 public Producer (ShareData s) { this.s = s; } public void run () { for (char ch = ‘A‘ ; ch <= ‘D‘ ; ch++) { try { Thread.sleep((int)(Math.random()*3000)); } catch (InterruptedException e) { e.printStackTrace(); } s.putShareChar(ch);// 将产品放入仓库 } } }
5、消费者线程
package com.ljb.app.communication; /** * 消费者线程 * @author LJB * @version 2015年3月11日 */ public class Consumer extends Thread{ // 共享资源 private ShareData s; // 构造方法 public Consumer (ShareData s) { this.s = s; } public void run () { char ch; do { try { Thread.sleep((int)(Math.random()*3000)); } catch (InterruptedException e) { e.printStackTrace(); } ch = s.getShareChar();// 从仓库中取出产品 } while (ch != ‘D‘); } }
6、测试类
package com.ljb.app.communication; /** * 测试类 * @author LJB * @version 2015年3月11日 */ public class Test { /** * @param args */ public static void main(String[] args) { ShareData s = new ShareData(); Thread consumer = new Consumer(s); consumer.start(); Thread producer = new Producer(s); producer.start(); } }
运行结果:
生产者还未生产,因此消费者停止消费。
生产者生产了产品A,通知消费者消费...
消费者消费了产品A,通知生产者生产...
生产者生产了产品B,通知消费者消费...
消费者消费了产品B,通知生产者生产...
生产者生产了产品C,通知消费者消费...
消费者消费了产品C,通知生产者生产...
生产者生产了产品D,通知消费者消费...
消费者消费了产品D,通知生产者生产...
时间: 2024-10-08 22:40:56