当前位置:首页 > Java

java线程如何同步和通讯

2026-03-17 19:12:06Java

Java线程同步与通信的方法

使用synchronized关键字

synchronized是Java中最基础的线程同步机制,可以修饰方法或代码块。当一个线程进入synchronized方法或代码块时,其他线程必须等待当前线程执行完毕才能进入。

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }
}

使用volatile关键字

volatile保证变量的可见性,即当一个线程修改了volatile变量的值,其他线程能立即看到最新值。但不保证原子性,适合单个变量的简单同步场景。

public class VolatileExample {
    private volatile boolean flag = false;
}

使用Lock接口

Java.util.concurrent.locks包提供了更灵活的锁机制,如ReentrantLock。相比synchronized,Lock提供了更多功能,如尝试获取锁、定时锁等待等。

Lock lock = new ReentrantLock();
public void method() {
    lock.lock();
    try {
        // 临界区代码
    } finally {
        lock.unlock();
    }
}

使用wait()/notify()机制

这是Java内置的线程间通信机制。wait()使线程等待并释放锁,notify()/notifyAll()唤醒等待的线程。必须在synchronized块中使用。

java线程如何同步和通讯

public synchronized void produce() throws InterruptedException {
    while (queue.isFull()) {
        wait();
    }
    // 生产数据
    notifyAll();
}

使用BlockingQueue

java.util.concurrent.BlockingQueue是线程安全的队列,提供了put()/take()等阻塞方法,天然适合生产者-消费者模式。

BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);
// 生产者
queue.put(item);
// 消费者
Integer item = queue.take();

使用CountDownLatch

CountDownLatch允许一个或多个线程等待其他线程完成操作。初始化时指定计数,countDown()减少计数,await()阻塞直到计数为0。

CountDownLatch latch = new CountDownLatch(3);
// 工作线程
latch.countDown();
// 主线程
latch.await();

使用CyclicBarrier

CyclicBarrier让一组线程互相等待,到达屏障点时才能继续执行。与CountDownLatch不同,它可以重置重用。

java线程如何同步和通讯

CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    // 所有线程到达后执行
});
// 线程中
barrier.await();

使用Semaphore

Semaphore控制同时访问特定资源的线程数量,通过acquire()获取许可,release()释放许可。

Semaphore semaphore = new Semaphore(5);
semaphore.acquire();
try {
    // 访问资源
} finally {
    semaphore.release();
}

使用Exchanger

Exchanger允许两个线程在同步点交换数据,适用于校对工作等场景。

Exchanger<String> exchanger = new Exchanger<>();
// 线程1
String data2 = exchanger.exchange(data1);
// 线程2
String data1 = exchanger.exchange(data2);

使用Future和Callable

通过ExecutorService提交Callable任务,返回Future对象,可以获取异步计算结果。

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> {
    return 1 + 1;
});
Integer result = future.get();

选择合适的方法取决于具体场景:简单同步用synchronized,复杂锁需求用Lock,线程协作用wait/notify或并发集合,任务协调用CountDownLatch/CyclicBarrier,资源控制用Semaphore。

标签: 线程通讯
分享给朋友:

相关文章

vue实现父子通讯

vue实现父子通讯

父组件向子组件传值(Props) 在父组件中通过v-bind(或简写为:)向子组件传递数据。子组件通过props接收数据。 父组件代码示例: <template> <Chil…

react两个页面之间如何通讯

react两个页面之间如何通讯

跨页面通信方法 使用URL参数传递数据 在React中可以通过路由的URL参数或查询字符串传递数据。使用react-router-dom的useNavigate和useLocation钩子实现。 /…

php实现线程

php实现线程

在PHP中实现多线程功能需要借助扩展或第三方库,因为PHP本身是单线程设计的语言。以下是几种常见的方法: 使用pthreads扩展(PHP 7以下版本) pthreads是一个PHP扩展,允许在PH…

js 实现线程

js 实现线程

在JavaScript中实现类似线程的功能可以通过以下几种方法实现,尽管JavaScript本身是单线程的,但通过异步编程或Web Worker可以实现并行处理的效果。 使用Web Worker W…

js实现线程池

js实现线程池

实现线程池的基本思路 JavaScript本身是单线程的,但可以通过Web Worker实现多线程。线程池的核心是管理多个Worker实例,避免频繁创建销毁的开销。 创建Worker管理类 cl…

java 线程如何关闭

java 线程如何关闭

关闭 Java 线程的方法 Java 线程的关闭可以通过多种方式实现,以下是几种常见的方法: 使用标志位控制线程退出 通过设置一个布尔类型的标志位,线程在运行时检查该标志位,决定是否退出。这种方式安…