/* * 多线程-消费者和生产者模式 * 在实现消费者生产者模式的时候必须要具备两个前提,一是,必须访问的是一个共享资源,二是必须要有线程锁,且锁的是同一个对象 * */
1 /*资源类中定义了name(名字):用来区分消费者还是生产者
2 * 定义了flag标记:用来区分有没有货物(默认生产一个就要消费一个)
3 * 定义了count(生产的个数统计)
4 * set方法:用来生产商品
5 * out方法:用来消费商品*/
6 class TestSource{
7 private String name=null;
8 private boolean flag=false;
9 private int count=0;
10 /*先通过flag标记判断有没有商品,有商品则等待,没有则生产商品,唤醒所有程序,并将flag标记改变*/
11 public synchronized void set(String name){
12 //判断是否有产品,这里用while循环,避免在多个生产者同时生产时,会出现生产多个产品,却只消费一个
13 while(flag){
14 try {
15 wait();
16 } catch (InterruptedException e) {
17 e.printStackTrace();
18 }
19 }
20 //生产产品并输出
21 this.name=name+"编号"+count++;
22 System.out.println("生产"+name+"++");
23 //改变标记
24 flag=true;
25 //唤醒所有的线程
26 notifyAll();
27 }
28 public synchronized void out(){
29 while(!flag){
30 try {
31 wait();
32 } catch (InterruptedException e) {
33 e.printStackTrace();
34 }
35 }
36 System.out.println("消费"+name+"---");
37 flag=false;
38 notifyAll();
39 }
40 }
41 class Product implements Runnable{
42 private TestSource ts=null;
43 //初始化线程里用到的资源
44 public Product(TestSource ts){
45 this.ts=ts;
46 }
47 //重写线程里run方法
48 public void run() {
49 while(true){
50 ts.set("生产产品");
51 }
52 }
53 }
54 class Customer implements Runnable{
55 private TestSource ts=null;
56 public Customer(TestSource ts){
57 this.ts=ts;
58 }
59 public void run() {
60 while(true){
61 ts.out();
62 }
63 }
64 }
65 public class test {
66 public static void main(String[] args) {
67 //初始化唯一的资源
68 TestSource ts=new TestSource();
69 //创建生产者和消费者两个对象,并传入两者共同操作的唯一资源
70 Customer cu=new Customer(ts);
71 Product pr=new Product(ts);
72 //将对象传入线程对象
73 Thread t1=new Thread(cu);
74 Thread t2=new Thread(pr);
75 Thread t3=new Thread(cu);
76 Thread t4=new Thread(pr);
77 //开启线程
78 t1.start();
79 t2.start();
80 t3.start();
81 t4.start();
82 }
83 }
/*在java1.5版本以后,用lock和unlick代替了synchronized关键字 * 用await()代替了wait()方法 * 用signal()代替了notify() * 这里的signal可以指定唤醒莫一类的线程,而不是像notifyAll,必须全部唤醒
这里我们对上面的代码进行一定的改写*/
1 class TestSource{
2 private String name=null;
3 private boolean flag=false;
4 private int count=0;
5 //定义lock,用来代替synchronized关键字
6 private Lock lock=new ReentrantLock();
7 private Condition condition_pro=lock.newCondition();
8 private Condition condition_con=lock.newCondition();
9 public void set(String name){
10 //对代码段进行上锁
11 lock.lock();
12 try {
13 while(flag){
14 try {
15 //wait();
16 //调用生产者控制方法
17 condition_pro.await();
18 } catch (InterruptedException e) {
19 e.printStackTrace();
20 }
21 }
22 this.name=name+"编号"+count++;
23 System.out.println("生产"+name+"++");
24 flag=true;
25 //notifyAll();
26 //唤醒消费者线程
27 condition_con.signal();
28 } finally{
29 //解锁,让其他进程进入访问
30 lock.unlock();
31 }
32
33
34 }
35 public void out(){
36 lock.lock();
37 try{
38 while(!flag){
39 try {
40 //wait();
41 condition_con.await();
42 } catch (InterruptedException e) {
43 e.printStackTrace();
44 }
45 }
46 System.out.println("消费"+name+"---");
47 flag=false;
48 //notifyAll();
49 condition_pro.signal();
50 }finally{
51 lock.unlock();
52 }
53
54 }
55 }