java如何阻塞
阻塞的概念
阻塞是指线程在执行过程中被暂停,直到某个条件满足才能继续执行。在Java中,阻塞通常用于多线程编程,以协调线程间的执行顺序或资源共享。
使用Object.wait()和notify()
通过Object类的wait()和notify()方法可以实现线程阻塞和唤醒。wait()使当前线程进入等待状态,直到其他线程调用notify()或notifyAll()。
synchronized (lockObject) {
while (!condition) {
lockObject.wait();
}
// 条件满足后继续执行
}
使用Lock和Condition
Java并发包中的Lock和Condition提供了更灵活的阻塞机制。Condition的await()方法类似于wait(),signal()类似于notify()。
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (!conditionMet) {
condition.await();
}
} finally {
lock.unlock();
}
使用BlockingQueue
BlockingQueue是一种线程安全的队列,当队列为空时,take()方法会阻塞;当队列满时,put()方法会阻塞。
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.put("item"); // 可能阻塞
String item = queue.take(); // 可能阻塞
使用CountDownLatch
CountDownLatch允许一个或多个线程等待其他线程完成操作。通过await()方法阻塞,直到计数器归零。
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
// 执行任务
latch.countDown();
}).start();
latch.await(); // 阻塞直到计数器归零
使用CyclicBarrier
CyclicBarrier让一组线程互相等待,到达屏障点时阻塞,直到所有线程都到达。
CyclicBarrier barrier = new CyclicBarrier(2);
new Thread(() -> {
barrier.await(); // 阻塞
}).start();
barrier.await(); // 阻塞
使用Semaphore
Semaphore通过许可机制控制资源访问。acquire()方法会阻塞,直到获得许可。
Semaphore semaphore = new Semaphore(1);
semaphore.acquire(); // 阻塞直到获得许可
try {
// 临界区
} finally {
semaphore.release();
}
使用Thread.join()
Thread.join()方法使当前线程等待目标线程执行完毕。
Thread thread = new Thread(() -> {
// 执行任务
});
thread.start();
thread.join(); // 阻塞直到thread结束
使用Future.get()
Future.get()方法会阻塞,直到异步任务完成并返回结果。
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> "result");
String result = future.get(); // 阻塞直到任务完成
使用SynchronousQueue
SynchronousQueue是一种特殊的阻塞队列,每个插入操作必须等待对应的移除操作。

SynchronousQueue<String> queue = new SynchronousQueue<>();
new Thread(() -> {
queue.take(); // 阻塞
}).start();
queue.put("item"); // 阻塞直到有消费者
注意事项
- 避免死锁,确保阻塞和唤醒的逻辑正确。
- 使用中断机制(InterruptedException)处理阻塞线程的取消。
- 根据场景选择合适的阻塞工具,例如生产者-消费者模型适合BlockingQueue。






