condition精准控制
Lock版的生产者消费者问题
那么在synchronized中呢,我们是使用wait和notify来控制线程的。
public synchronized void increment() throws InterruptedException { while (number != 0) { // 等待 this.wait(); } Thread.sleep(100); number++; // 业务 System.out.println(Thread.currentThread().getName() + " => " + number); // 通知其它线程我+1加完了 this.notifyAll(); }
用了Lock之后、会有一些细微的改变,wait->condition.await, notify->condition.signal
class doSomething { private int number = 0; Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); // +1 public void increse() throws InterruptedException { lock.lock(); try { while (number != 0) { condition.await(); } Thread.sleep(100); number++; System.out.println(Thread.currentThread().getName() + "->" + number); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } // -1 public void decrese() throws InterruptedException { lock.lock(); try { while (number == 0) { condition.await(); } Thread.sleep(100); number--; System.out.println(Thread.currentThread().getName() + "->" + number); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
思考:既然有了wait和notify、那为什么我们还要多此一举来使用condition的等待和唤醒呢?
这是因为condition能够做到有序,精准的通知和唤醒线程
那么如何做到有序精准的来唤醒线程呢?
public class C { public static void main(String[] args) { doSomething2 doSomething2 = new doSomething2(); new Thread(() -> { for (int i = 0; i < 10; i++) { doSomething2.printA(); } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { doSomething2.printB(); } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { doSomething2.printC(); } }, "C").start(); } } @SuppressWarnings("all") class doSomething2 { private int number = 1; Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); public void printA() { lock.lock(); try { while (number != 1) { // 等待 condition1.await(); } Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "AAA"); // 唤醒 condition2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printB() { lock.lock(); try { while (number != 1) { // 等待 condition2.await(); } Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "BBB"); // 唤醒 condition3.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printC() { lock.lock(); try { while (number != 1) { // 等待 condition3.await(); } Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "CCC"); // 唤醒 condition1.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
posted on 2021-06-07 22:44 Love&Share 阅读(76) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~