位置: 文档库 > Java > 文档下载预览

《Java中使用Condition实现线程通信.doc》

1. 下载的文档为doc格式,下载后可用word或者wps进行编辑;

2. 将本文以doc文档格式下载到电脑,方便收藏和打印;

3. 下载后的文档,内容与下面显示的完全一致,下载之前请确认下面内容是否您想要的,是否完整.

点击下载文档

Java中使用Condition实现线程通信.doc

《Java中使用Condition实现线程通信》

在Java多线程编程中,线程间的通信与同步是核心问题之一。传统的`synchronized`关键字结合`wait()`和`notify()`方法可以实现基本的线程协作,但存在灵活性不足、无法精准控制唤醒特定线程等问题。Java 5引入的`java.util.concurrent.locks.Condition`接口,通过与`Lock`配合使用,提供了更细粒度的线程控制能力,成为解决复杂线程通信场景的利器。

一、Condition的核心概念

Condition是`Lock`接口的配套组件,用于替代`Object`的`wait()`/`notify()`机制。其核心优势在于:

  • 多条件队列:一个`Lock`对象可关联多个`Condition`,实现更复杂的线程分组唤醒
  • 公平性控制:支持公平/非公平锁模式下的条件等待
  • 中断响应**:提供`awaitInterruptibly()`等支持中断的方法

典型使用模式:

Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();

lock.lock();
try {
    while (条件不满足) {
        condition.await(); // 释放锁并等待
    }
    // 执行临界区操作
    condition.signal(); // 唤醒一个等待线程
} finally {
    lock.unlock();
}

二、Condition的核心方法解析

1. **等待方法**:

  • await():释放锁并进入等待状态,直到被唤醒
  • awaitUninterruptibly():忽略中断的等待
  • await(long time, TimeUnit unit):超时等待

2. **唤醒方法**:

  • signal():唤醒一个等待线程
  • signalAll():唤醒所有等待线程

3. **与Object方法对比**:

Object方法 Condition方法 特点
wait() await() 自动释放锁
notify() signal() 单线程唤醒
notifyAll() signalAll() 多线程唤醒

三、经典应用场景实现

1. 生产者-消费者模型

传统实现存在虚假唤醒问题,Condition方案更可靠:

class BoundedBuffer {
    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    private final Object[] items = new Object[100];
    private int putptr, takeptr, count;

    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length)
                notFull.await();
            items[putptr] = x;
            if (++putptr == items.length) putptr = 0;
            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0)
                notEmpty.await();
            Object x = items[takeptr];
            if (++takeptr == items.length) takeptr = 0;
            --count;
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }
}

2. 线程池任务调度

实现带条件的任务队列:

class ConditionTaskQueue {
    private final Queue tasks = new LinkedList();
    private final Lock lock = new ReentrantLock();
    private final Condition hasTasks = lock.newCondition();

    public void addTask(Runnable task) {
        lock.lock();
        try {
            tasks.add(task);
            hasTasks.signal(); // 通知消费者
        } finally {
            lock.unlock();
        }
    }

    public Runnable takeTask() throws InterruptedException {
        lock.lock();
        try {
            while (tasks.isEmpty()) {
                hasTasks.await(); // 等待任务
            }
            return tasks.poll();
        } finally {
            lock.unlock();
        }
    }
}

3. 读写锁优化实现

自定义读写锁中的条件控制:

class CustomReadWriteLock {
    private int readers = 0;
    private int writers = 0;
    private int writeRequests = 0;
    private final Lock lock = new ReentrantLock();
    private final Condition readCondition = lock.newCondition();
    private final Condition writeCondition = lock.newCondition();

    public void lockRead() throws InterruptedException {
        lock.lock();
        try {
            while (writers > 0 || writeRequests > 0) {
                readCondition.await();
            }
            readers++;
        } finally {
            lock.unlock();
        }
    }

    public void unlockRead() {
        lock.lock();
        try {
            readers--;
            if (readers == 0 && writeRequests > 0) {
                writeCondition.signal();
            }
        } finally {
            lock.unlock();
        }
    }
}

四、Condition使用注意事项

1. **锁的获取顺序**:

必须先获取`Lock`再操作`Condition`,否则会抛出`IllegalMonitorStateException`。错误示例:

Condition cond = lock.newCondition();
cond.await(); // 错误!未获取锁

2. **虚假唤醒问题**:

必须使用`while`循环检查条件,而非`if`语句:

// 错误写法
if (queue.isEmpty()) {
    cond.await();
}

// 正确写法
while (queue.isEmpty()) {
    cond.await();
}

3. **中断处理**:

优先使用`awaitInterruptibly()`处理中断:

try {
    condition.awaitInterruptibly();
} catch (InterruptedException e) {
    // 处理中断
    Thread.currentThread().interrupt();
}

4. **性能考量**:

  • 避免频繁创建`Condition`对象
  • 合理选择`signal()`和`signalAll()`
  • 在简单场景下`synchronized`可能更高效

五、Condition与Synchronized对比

特性 synchronized Condition
锁对象 任意对象 必须通过Lock创建
条件队列 单个 多个
公平性 不可控 可配置
超时等待 有限支持 完整支持
中断响应 不支持 完整支持

六、高级应用技巧

1. **多条件变量协作**:

实现优先级队列的线程调度:

class PriorityQueue {
    private final Lock lock = new ReentrantLock();
    private final Condition highPriority = lock.newCondition();
    private final Condition lowPriority = lock.newCondition();
    private int highCount = 0;

    public void addHighPriority(Runnable task) {
        lock.lock();
        try {
            highCount++;
            highPriority.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public Runnable takeHighPriority() throws InterruptedException {
        lock.lock();
        try {
            while (highCount == 0) {
                highPriority.await();
            }
            highCount--;
            return () -> System.out.println("High priority task");
        } finally {
            lock.unlock();
        }
    }
}

2. **条件传播**:

实现链式条件唤醒:

class ConditionChain {
    private final Lock lock = new ReentrantLock();
    private final Condition first = lock.newCondition();
    private final Condition second = lock.newCondition();
    private boolean state = false;

    public void step1() throws InterruptedException {
        lock.lock();
        try {
            while (!state) {
                first.await();
            }
            System.out.println("Step 1 completed");
            second.signal();
        } finally {
            lock.unlock();
        }
    }

    public void trigger() {
        lock.lock();
        try {
            state = true;
            first.signalAll();
        } finally {
            lock.unlock();
        }
    }
}

3. **定时条件**:

实现带超时的资源获取:

class TimeoutResource {
    private final Lock lock = new ReentrantLock();
    private final Condition available = lock.newCondition();
    private boolean isAvailable = false;

    public String acquireWithTimeout(long timeout, TimeUnit unit) 
        throws InterruptedException, TimeoutException {
        
        lock.lock();
        try {
            long remaining = unit.toNanos(timeout);
            while (!isAvailable) {
                if (remaining 

七、常见问题解决方案

1. **死锁问题**:

典型场景:

// 错误示例:可能导致死锁
public void methodA() {
    lockA.lock();
    try {
        lockB.lock();
        try {
            // 操作
        } finally {
            lockB.unlock();
        }
    } finally {
        lockA.unlock();
    }
}

public void methodB() {
    lockB.lock();
    try {
        lockA.lock();
        try {
            // 操作
        } finally {
            lockA.unlock();
        }
    } finally {
        lockB.unlock();
    }
}

解决方案:按固定顺序获取锁

2. **条件判断遗漏**:

错误示例:

// 错误:可能虚假唤醒
if (queue.size() = MAX_SIZE) {
    // 等待
}
// 处理后
if (等待线程存在) {
    notFull.signal();
}

3. **性能瓶颈**:

优化策略:

  • 减少锁持有时间
  • 合理划分临界区
  • 使用读写锁分离读操作

八、最佳实践总结

1. **设计模式选择**:

  • 简单场景:优先使用`synchronized`
  • 复杂条件:使用`Condition`
  • 需要中断:必须使用`Condition`

2. **代码结构规范**:

// 标准模板
public void method() {
    lock.lock();
    try {
        while (条件不满足) {
            condition.await();
        }
        // 临界区操作
        // 修改共享变量
        condition.signalAll(); // 或 signal()
    } catch (InterruptedException e) {
        // 处理中断
        Thread.currentThread().interrupt();
    } finally {
        lock.unlock();
    }
}

3. **监控与调试**:

  • 添加日志记录锁获取情况
  • 使用JConsole监控线程状态
  • 设置合理的超时时间

4. **测试策略**:

  • 单元测试覆盖中断场景
  • 压力测试验证并发性能
  • 边界条件测试(空队列、满队列等)

关键词:Java多线程、Condition接口、线程通信、Lock机制、生产者消费者模型、线程同步、虚假唤醒、中断处理、多条件队列

简介:本文详细解析了Java中Condition接口的实现原理和使用方法,通过对比synchronized机制阐述其优势,结合生产者-消费者模型、线程池调度等经典场景展示具体应用,深入探讨了虚假唤醒、中断处理等关键问题的解决方案,最后总结了最佳实践和性能优化策略,为开发者提供完整的Condition使用指南。

《Java中使用Condition实现线程通信.doc》
将本文以doc文档格式下载到电脑,方便收藏和打印
推荐度:
点击下载文档