Java中同步与并发用法分析

yizhihongxing

Java中同步与并发用法分析

同步

在Java中,同步是指多个线程之间访问共享资源的时候,保证线程安全的机制。Java提供了两种机制来实现同步:synchronized关键字和Lock接口。

synchronized关键字

synchronized关键字可以用于修饰方法或代码块。被修饰的方法或代码块在同一时间只能被一个线程执行,其他线程需要等待。

示例代码:

public class ThreadSafeExample {
    private int count = 0;

    // synchronized关键字修饰方法
    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

在上述例子中,increment()方法被synchronized关键字修饰,意味着在同一时间只有一个线程能够访问它。如果不加synchronized关键字,多个线程同时访问increment()方法可能会出现线程安全问题。

Lock接口

Lock接口提供了与synchronized关键字类似的同步机制,也可以用于保证多个线程之间的线程安全。

示例代码:

public class ThreadSafeExample {
    private int count = 0;
    private Lock lock = new ReentrantLock();  // 实例化Lock接口对象

    public void increment() {
        lock.lock();  // 加锁
        try {
            count++;
        } finally {
            lock.unlock();  // 解锁
        }
    }

    public int getCount() {
        return count;
    }
}

在上述例子中,我们使用了Lock接口提供的ReentrantLock实现类来实例化lock对象。在increment()方法中,我们调用了lock()方法加锁,finally中调用了unlock()方法解锁。这样,在同一时间只有一个线程能够访问increment()方法,可以保证线程安全。

并发

Java中的并发是指多个线程同时执行,在同一时间内,每个线程都可以访问共享资源。

Java提供了多种工具来处理并发,最常用的有:

  • Semaphore信号量
  • CountDownLatch计数器
  • CyclicBarrier屏障

Semaphore信号量

Semaphore可以用来控制同时访问共享资源的线程数量。Semaphore类似于一个计数器,可以通过acquire()和release()方法来控制资源的访问。

示例代码:

public class SemaphoreExample {
    private static final int THREAD_COUNT = 10;
    private static Semaphore semaphore = new Semaphore(5);  // 实例化Semaphore对象,初始许可数量为5

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 0; i < THREAD_COUNT; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();  // 获取许可
                    System.out.println(Thread.currentThread().getName() + " acquire a permit");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();  // 释放许可
                    System.out.println(Thread.currentThread().getName() + " release a permit");
                }
            });
        }

        executorService.shutdown();
    }
}

在上述例子中,Semaphore的初始许可数量为5,每个线程获取一个许可,线程执行结束后释放许可。最多只有5个线程能够同时占用许可,其他线程需要等待。

CountDownLatch计数器

CountDownLatch可以用来实现等待其他线程执行完毕之后再进行操作。CountDownLatch的初始计数器数量为线程个数,每个线程执行完后计数器数量减1,当计数器数量为0时,await()方法才会返回。

示例代码:

public class CountDownLatchExample {
    private static final int THREAD_COUNT = 5;
    private static CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNT);  // 实例化CountDownLatch对象,计数器数量为5

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 0; i < THREAD_COUNT; i++) {
            executorService.execute(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " started");
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName() + " ended");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();  // 计数器减1
                }
            });
        }

        countDownLatch.await();  // 等待计数器归零

        System.out.println("All threads have finished.");
        executorService.shutdown();
    }
}

在上述例子中,我们创建了5个线程,执行其中的任务,任务执行完成后调用countDown()方法减少计数器数量。执行主线程中,通过await()方法等待所有线程执行完毕,当计数器数量变为0时,执行主线程中的代码。

CyclicBarrier屏障

CyclicBarrier可以用来在多个线程之间创建一个屏障,只有所有线程到达屏障时,才会继续执行后续操作。

示例代码:

public class CyclicBarrierExample {
    private static final int THREAD_COUNT = 5;
    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(THREAD_COUNT, () -> {
        System.out.println("All threads have reached the barrier.");
    });  // 实例化CyclicBarrier对象,等待线程数量为5

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 0; i < THREAD_COUNT; i++) {
            executorService.execute(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " started");
                    Thread.sleep(2000);
                    cyclicBarrier.await();  // 等待其他线程到达屏障
                    System.out.println(Thread.currentThread().getName() + " ended");
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            });
        }

        executorService.shutdown();
    }
}

在上述例子中,我们创建了5个线程,执行其中的任务,并在其中增加了cyclicBarrier.await()方法。当线程调用这个方法时,它就等待其他线程也到达这个屏障。当所有线程都到达屏障时,CyclicBarrier的内部计数器就会被重置为其初始值,并启动一个可选的Runnable。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中同步与并发用法分析 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • java多线程之CyclicBarrier的使用方法

    Java多线程之CyclicBarrier的使用方法 简介 CyclicBarrier是Java多线程中的一个工具类,它可以用来构建可重用的同步对象,可以让一组线程在到达某个屏障时阻塞,直到所有的线程都到达屏障时,在继续执行。与CountDownLatch类似,都是多线程同步工具,但CyclicBarrier可以通过它的reset()方法,重用一次。 Cyc…

    多线程 2023年5月16日
    00
  • Java多线程并发编程 Synchronized关键字

    Java多线程并发编程Synchronized关键字 什么是Synchronized关键字? 在Java多线程并发编程中,Synchronized关键字可以用来保证多个线程在访问共享资源时的同步性。它可以实现线程安全的同步操作。 Synchronized关键字的用法 Synchronized关键字可以加在方法和代码块上面。 方法上的Synchronized关…

    多线程 2023年5月16日
    00
  • 使用JMeter进行接口高并发测试的实现

    下面针对”使用JMeter进行接口高并发测试的实现”给出完整攻略。 一、准备工作 1. 安装JMeter 在JMeter官网下载最新版本的JMeter并安装。 2. 准备测试数据 需要准备待测试的接口,并了解每个接口的参数和请求方法。 3. 新建并配置JMeter测试计划 在JMeter中新建一个测试计划,配置相关属性,如线程数、循环次数以及各个Sample…

    多线程 2023年5月16日
    00
  • 基于rocketmq的有序消费模式和并发消费模式的区别说明

    基于RocketMQ的有序消费模式和并发消费模式的区别说明 1. 有序消费模式 在有序消费模式下,消息消费是按照消息的发送顺序依次进行的。具体实现方式是,消息生产者将消息发送到同一个Message Queue中,而Message Queue按照顺序将消息发送给Consumer进行消费。因此,在有序消费模式下,同一个Message Queue的消息一定会按照发…

    多线程 2023年5月17日
    00
  • Java并发系列之ReentrantLock源码分析

    当然,我很愿意为您讲解《Java并发系列之ReentrantLock源码分析》的完整攻略。 Java并发系列之ReentrantLock源码分析 一、ReentrantLock概述 ReentrantLock是Java提供的一种基于互斥锁的同步机制,它比synchronized更加灵活和强大,能够支持更复杂的同步需求。在Java并发编程中,Reentrant…

    多线程 2023年5月17日
    00
  • PHP解决高并发的优化方案实例

    PHP解决高并发的优化方案实例 近年来,随着互联网用户数量的飞速增长,高并发成为了许多网站开发者不得不面对的一个问题。对于使用PHP等后端语言的网站来说,如何针对高并发情况进行优化,将是一个非常重要的课题。以下是一些常见的PHP解决高并发问题的优化方案实例。 1. CDN加速 CDN(Content Delivery Network)即内容分发网络,是一种可…

    多线程 2023年5月16日
    00
  • java线程池:获取运行线程数并控制线程启动速度的方法

    Java线程池:获取运行线程数并控制线程启动速度的方法 线程池是 Java 多线程编程中一个非常重要的组件,常用来管理线程的创建、分配、执行、回收等功能,从而更加高效地利用 CPU 资源,避免频繁创建和销毁线程导致的性能开销和资源浪费。 在使用线程池时,如何获取当前线程池的运行线程数,并控制线程的启动速度,特别是在高并发场景下,这是一个非常重要的问题。以下是…

    多线程 2023年5月16日
    00
  • IOS多线程编程的3种实现方法

    IOS多线程编程的3种实现方法 在IOS开发中,多线程编程是非常重要的一项技能。它可以使我们的应用程序更加流畅和安全。本文将介绍IOS多线程编程的3种实现方法,分别是NSThread,GCD和NSOperation。 1. NSThread NSThread是iOS提供的一种轻量级的多线程实现方法。我们可以通过以下步骤创建和启动一个线程: NSThread …

    多线程 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部