线程中消费者生产者的实例代码(使用Lock类)

简介:

 

Lock可以替换synchronized.

上面用来做为锁对象的SaleWindow.class没有别的操作,而且获取锁和释放锁都是在内部隐藏完成的.

Java的思想是万物皆对象,我们把这种锁也描述成为一个对象,就是Lock.....

Lock中的lock和unlock显式的打开和关闭(可视化)更直观.

Lock实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作.

此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的Condition对象.

 

Lock可以替换synchronized.

 使用synchronized

synchronized(SaleWindow.class) {

 

}

SaleWindow.class 这个锁对象没有别的操作,而且这个锁对象获取锁和释放锁的操作都是在内部隐藏的完成的,而Java的思想是万物皆对象.

我们把这种锁也描述成了一个对象,这个对象就是Lock.

Lock中获取锁和释放锁都提供了对应的方法,这两种操作都是一种显式的操作,更直观的表示了这个问题.

 

如果仅仅把之间的synchronized替换成Lock运行是会报错的.

 

原因就是锁替换了synchronized 但是wait只能在同步中调用.

我们应该把wait 和 notify 等待唤醒机制都替换掉.

 

上面说的Condition是将Object监视器方法(wait,notify和notifyAll)分解成截然不同的对象,以便通过这些对象与任意Lock实现组合使用,为每个对象提供多个等待...其中Lock替代了synchronized方法和语句的使用,Condition替代了Object监视器方法的使用.

Condition中有await()  signal()  和 signalAll().....

 

SaleWindow.java

复制代码
 1 import java.util.List;
 2 import java.util.Random;
 3 import java.util.concurrent.TimeUnit;
 4 import java.util.concurrent.locks.Condition;
 5 import java.util.concurrent.locks.Lock;
 6 
 7 public class SaleWindow implements Runnable {
 8 
 9     private List<Food> foods;
10 
11     public List<Food> getFoods() {
12         return foods;
13     }
14 
15     public void setFoods(List<Food> foods) {
16         this.foods = foods;
17     }
18 
19     public SaleWindow(List<Food> foods) {
20         this.foods = foods;
21     }
22 
23     public SaleWindow() {
24     }
25 
26     public void sale() {
27         while (true) {
28             // 加锁
29             Lock lock = MyLock.LOCK;
30             Condition cook_con =  MyLock.COOK_CON;
31             Condition sale_con =  MyLock.SALE_CON;
32             lock.lock();
33             if (foods.size() > 0) {
34                 try {
35                     Food food = foods.get(0);
36                     System.out.println(Thread.currentThread().getName()
37                             + ": 卖出了 " + food.getId() + " 号饭...");
38                     Random ran = new Random();
39                     int i = ran.nextInt(300);
40 
41                     TimeUnit.MILLISECONDS.sleep(i);
42                     foods.remove(0);
43                     // SaleWindow.class.notify();//随机唤醒一条等待的线程
44                     cook_con.signal();
45                 } catch (InterruptedException e) {
46                     e.printStackTrace();
47                 }
48             } else {
49                 System.out.println(Thread.currentThread().getName()
50                         + ":饭买完了。厨师赶紧做,我休息了。。。");
51                 try {
52                     sale_con.await();
53                 } catch (InterruptedException e) {
54                     e.printStackTrace();
55                 }
56 
57             }
58             // 释放锁
59             lock.unlock();
60         }
61     }
62 
63     @Override
64     public void run() {
65         sale();
66     }
67 
68 }
复制代码

  Cook.java

复制代码
 1 import java.util.List;
 2 import java.util.Random;
 3 import java.util.concurrent.TimeUnit;
 4 import java.util.concurrent.locks.Condition;
 5 import java.util.concurrent.locks.Lock;
 6 
 7 public class Cook implements Runnable {
 8 
 9     private List<Food> foods;
10     private static int num = 1;
11     private static final int MAXSIZE = 1;
12 
13     public List<Food> getFoods() {
14         return foods;
15     }
16 
17     public void setFoods(List<Food> foods) {
18         this.foods = foods;
19     }
20 
21     public Cook(List<Food> foods) {
22         this.foods = foods;
23     }
24 
25     public Cook() {
26     }
27 
28     public void produce() {
29         while (true) {
30             Lock lock = MyLock.LOCK;
31             Condition cook_con =  MyLock.COOK_CON;
32             Condition sale_con =  MyLock.SALE_CON;
33             lock.lock();
34             if (foods.size() < MAXSIZE) {
35                 Food food = new Food((num++) + "");
36                 foods.add(food);
37                 System.out.println(Thread.currentThread().getName() + " :做好 "
38                         + food.getId() + " 号饭了");
39                 Random ran = new Random();
40                 int i = ran.nextInt(300);
41                 try {
42                     TimeUnit.MILLISECONDS.sleep(i);
43                 } catch (InterruptedException e) {
44                     e.printStackTrace();
45                 }
46 
47                 // SaleWindow.class.notify();
48 
49                 sale_con.signal();//唤醒等待中的一条线程
50             } else {
51                 System.out.println(Thread.currentThread().getName()
52                         + " :桌子放满了。窗口赶紧卖,我休息了。。。");
53 
54                 try {
55                     cook_con.await();
56                 } catch (InterruptedException e) {
57                     e.printStackTrace();
58                 }
59             }
60             lock.unlock();
61         }
62 
63     }
64 
65     @Override
66     public void run() {
67         produce();
68     }
69 }
复制代码

 Food.java

复制代码
 1 public class Food {
 2 
 3     private String id;
 4 
 5     
 6     public Food(String id) {
 7         this.id = id;
 8     }
 9 
10     public String getId() {
11         return id;
12     }
13 
14     public void setId(String id) {
15         this.id = id;
16     }
17     
18     
19 }
复制代码

 MyLock.java

复制代码
 1 import java.util.concurrent.locks.Condition;
 2 import java.util.concurrent.locks.Lock;
 3 import java.util.concurrent.locks.ReentrantLock;
 4     //把锁抽取出来.
 5 public class MyLock {
 6     
 7     public static final Lock LOCK = new ReentrantLock(true);//公平模式
 8     public static final Condition COOK_CON = LOCK.newCondition();//监视Cook的监视器
 9     public static final Condition SALE_CON = LOCK.newCondition();//监视Sale的监视器 
10     //两个监视器之间可以相互通知 本方唤醒对方的等待中的一条线程.
11     
12     //构造方法私有 单例  饿汉式
13     private MyLock(){}
14 }
复制代码

 Test.java

复制代码
 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 public class Test {
 5 
 6     public static void main(String[] args) {
 7         
 8         /*List<Food> foods = new ArrayList<Food>();
 9         for (int i = 0; i < 10; i++) {
10             foods.add(new Food((i+1)+""));
11         }
12         Restaurant r = new Restaurant(foods);
13         for (int i = 0; i < 3; i++) {
14             new Thread(r).start();
15         }*/
16         List<Food> foods = new ArrayList<Food>();
17         for (int i = 0; i < 4; i++) {
18             new Thread(new Cook(foods),"Cook"+(i+1)).start();
19         }
20         for (int i = 0; i < 3; i++) {
21             new Thread(new SaleWindow(foods),"sale"+(i+1)).start();
22         }
23     }
24 }
复制代码

 


本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/6204665.html,如需转载请自行联系原作者

相关文章
|
21天前
|
供应链 安全 NoSQL
PHP 互斥锁:如何确保代码的线程安全?
在多线程和高并发环境中,确保代码段互斥执行至关重要。本文介绍了 PHP 互斥锁库 `wise-locksmith`,它提供多种锁机制(如文件锁、分布式锁等),有效解决线程安全问题,特别适用于电商平台库存管理等场景。通过 Composer 安装后,开发者可以利用该库确保在高并发下数据的一致性和安全性。
33 6
|
1月前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
1月前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
45 4
|
2月前
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
Lua的面向对象编程、协同线程与协同函数的概念和使用,以及Lua文件I/O操作的基本方法。
32 4
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
26 3
|
2月前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
46 2
|
2月前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
35 2
|
2月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
24 1
|
2月前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
41 1
|
2月前
|
Java 开发者
在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选
【10月更文挑战第6天】在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选。相比 `synchronized`,Lock 提供了更灵活强大的线程同步机制,包括可中断等待、超时等待、重入锁及读写锁等高级特性,极大提升了多线程应用的性能和可靠性。通过示例对比,可以看出 Lock 接口通过 `lock()` 和 `unlock()` 明确管理锁的获取和释放,避免死锁风险,并支持公平锁选择和条件变量,使其在高并发场景下更具优势。掌握 Lock 接口将助力开发者构建更高效、可靠的多线程应用。
26 2