当前位置: 技术文章>> Java中的并发库(java.util.concurrent)提供了哪些工具类?

文章标题:Java中的并发库(java.util.concurrent)提供了哪些工具类?
  • 文章分类: 后端
  • 7090 阅读

Java中的并发库(java.util.concurrent)是Java平台提供的一组高级并发编程工具,它极大地简化了多线程编程的复杂性,使得开发者能够更高效地编写出高并发、高性能的应用程序。这个库涵盖了多种工具类,用于处理线程间的同步、协调、数据共享等问题。以下是对java.util.concurrent包中一些关键工具类的详细解析,这些工具类在并发编程中扮演着重要角色。

1. 线程池(ExecutorService)

线程池是管理一组线程的框架,它可以重用线程,减少线程创建和销毁的开销。java.util.concurrent包提供了ExecutorService接口以及多种实现,如ThreadPoolExecutor和ScheduledThreadPoolExecutor。使用线程池可以方便地控制线程的数量,避免创建过多的线程导致系统资源耗尽。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        // 创建一个固定大小的线程池
        ExecutorService executor = Executors.newFixedThreadPool(5);
        
        // 提交任务
        for (int i = 0; i < 10; i++) {
            executor.submit(new Task(i));
        }
        
        // 关闭线程池
        executor.shutdown();
    }

    static class Task implements Runnable {
        private int taskId;

        public Task(int taskId) {
            this.taskId = taskId;
        }

        @Override
        public void run() {
            System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
        }
    }
}

2. 锁(Locks)

Java并发库提供了比内置锁(synchronized)更灵活的锁定机制,如ReentrantLock和ReentrantReadWriteLock等。这些锁提供了更细粒度的控制,比如可中断的锁获取、可定时的锁尝试以及公平锁等特性。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockExample {
    private static int counter = 0;
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            lock.lock();
            try {
                for (int i = 0; i < 10000; i++) {
                    counter++;
                }
            } finally {
                lock.unlock();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Counter: " + counter);
    }
}

3. 原子变量(Atomic Variables)

原子变量提供了无锁的线程安全操作,适用于高并发场景。Java并发库提供了多种原子变量类,如AtomicInteger、AtomicLong等。这些类利用底层的CAS(Compare-And-Swap)操作来确保变量更新的原子性。

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicExample {
    private static AtomicInteger counter = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            for (int i = 0; i < 10000; i++) {
                counter.incrementAndGet();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Counter: " + counter.get());
    }
}

4. 并发集合(Concurrent Collections)

Java并发库提供了多种线程安全的集合类,如ConcurrentHashMap、ConcurrentLinkedQueue等。这些集合类通过内部机制(如分段锁、CAS操作等)确保了多线程环境下的高效并发访问。

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) throws InterruptedException {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        Runnable putTask = () -> {
            for (int i = 0; i < 1000; i++) {
                map.put("Key" + i, i);
            }
        };

        Runnable getTask = () -> {
            for (int i = 0; i < 1000; i++) {
                map.get("Key" + i);
            }
        };

        Thread t1 = new Thread(putTask);
        Thread t2 = new Thread(getTask);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Map size: " + map.size());
    }
}

5. 同步工具类

除了上述的线程池、锁、原子变量和并发集合外,java.util.concurrent包还提供了多种用于线程同步和协调的工具类,如CountDownLatch、CyclicBarrier和Semaphore等。

  • CountDownLatch:允许一个或多个线程等待其他线程完成操作。它基于一个计数器,每当一个线程完成任务时,计数器的值就减一,当计数器为零时,等待的线程会被唤醒继续执行。
import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        int numStudents = 3;
        CountDownLatch latch = new CountDownLatch(numStudents);

        for (int i = 0; i < numStudents; i++) {
            Student student = new Student(latch, "Student " + (i + 1));
            new Thread(student).start();
        }

        latch.await(); // 等待所有学生考试完成

        // 计算学生平均分
        int totalScore = 0;
        for (int i = 0; i < numStudents; i++) {
            totalScore += Student.scores[i];
        }

        double averageScore = (double) totalScore / numStudents;
        System.out.println("所有学生的平均分为: " + averageScore);
    }

    static class Student implements Runnable {
        private final CountDownLatch latch;
        private final String name;

        public static int[] scores = new int[3];

        public Student(CountDownLatch latch, String name) {
            this.latch = latch;
            this.name = name;
        }

        @Override
        public void run() {
            // 模拟学生考试
            int score = (int) (Math.random() * 100);
            System.out.println(name + "结束考试,分数为:" + score);

            // 保存成绩并减少计数器
            int index = Integer.parseInt(name.split(" ")[1]) - 1;
            scores[index] = score;
            latch.countDown();
        }
    }
}
  • CyclicBarrier:允许多个线程相互等待,直到所有线程都到达一个屏障点后再继续执行。它类似于一个可重用的CountDownLatch,但它允许多次使用,每次使用都会重置计数器。

  • Semaphore:是一种计数信号量,它允许多个线程同时访问共享资源,并通过计数器来控制访问数量。它通常用于限制同时访问某个资源的线程数。

这些工具类在并发编程中扮演着重要角色,它们各自具有不同的应用场景和优势。开发者可以根据具体需求选择合适的工具类来解决并发编程中的问题。

总结

Java中的并发库(java.util.concurrent)提供了丰富的工具和类,包括线程池、锁、原子变量、并发集合以及同步工具类等。这些工具和类极大地简化了多线程编程的复杂性,提高了并发编程的效率和安全性。通过合理使用这些工具和类,开发者可以编写出高效、稳定、可维护的并发应用程序。在实际开发中,建议开发者深入理解这些工具和类的原理和用法,以便更好地应对复杂的并发编程场景。

推荐文章