本文共 6576 字,大约阅读时间需要 21 分钟。
在Java多线程编程中,多线程是提升程序效率的重要手段。多个线程能够同时执行不同的任务,从而大大提高程序的运行速度。然而,多线程编程也需要有序地管理线程之间的协作与资源共享。以下将从Semaphore、CountDownLatch、CyclicBarrier、Lock以及Condition等多线程控制工具进行详细讲解。
Semaphore是一种轻量级的同步机制,常用于资源的互相独占或共享。它类似于操作系统中的信号灯,用于限制某种资源的使用数量。Semaphore的典型应用场景包括线程池、数据库连接池等。
public class SemaphoreDemo { private static Semaphore semaphore = new Semaphore(3); // 初始化信号灯,允许最多3个线程同时通过 public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(50); // 创建一个固定的线程池,线程数量为50 for (int i = 0; i < 1000; i++) { service.submit(new Task()); // 提交1000个任务到线程池中执行 } service.shutdown(); // 关闭线程池,等待所有任务完成 } private static class Task implements Runnable { @Override public void run() { try { semaphore.acquire(); // 请求信号灯,等待许可 System.out.println(Thread.currentThread().getName() + "拿到了信号灯,开始执行"); Thread.sleep(2000); // 模拟耗时操作 System.out.println(Thread.currentThread().getName() + "执行完毕,归还信号灯"); semaphore.release(); // 释放信号灯,允许其他线程通过 } catch (InterruptedException e) { e.printStackTrace(); } } }} CountDownLatch是一个用于线程间有序执行的工具。它允许一个线程或多个线程等待其他线程完成特定任务后再继续执行。CountDownLatch的默认行为是只能使用一次,但如果需要多次使用,可以使用CyclicBarrier。
public class CountDownLatchDemo { private static CountDownLatch countDownLatch = new CountDownLatch(3); public static void main(String[] args) throws InterruptedException { // 创建三个任务,每个任务都会等待CountDownLatch的完成 for (int i = 0; i < 3; i++) { new Thread(new Task("任务" + (i + 1), countDownLatch)).start(); } System.out.println("等待三个任务完成"); countDownLatch.await(); // 等待所有任务完成 System.out.println("所有任务已经完成"); } private static class Task implements Runnable { private String taskName; private CountDownLatch countDownLatch; public Task(String taskName, CountDownLatch countDownLatch) { this.taskName = taskName; this.countDownLatch = countDownLatch; } @Override public void run() { System.out.println("任务" + taskName + "开始执行"); try { Thread.sleep(1000); // 模拟耗时操作 System.out.println("任务" + taskName + "已经完成"); countDownLatch.countDown(); // 倒计时减一,当倒计时减到零时,等待线程才会继续 } catch (InterruptedException e) { e.printStackTrace(); } } }} CyclicBarrier是一种可以多次使用的栅栏,它支持线程间的协作。与CountDownLatch不同,CyclicBarrier可以多次重复使用,适用于需要多次等待其他线程完成的场景。
public class CyclicBarrierDemo { public static void main(String[] args) throws Exception { CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println("有3个线程已经到达,准备出发"); } }); for (int i = 0; i < 6; i++) { new Thread(new Task(i + 1, cyclicBarrier)).start(); } } private static class Task implements Runnable { private int id; private CyclicBarrier cyclicBarrier; public Task(int id, CyclicBarrier cyclicBarrier) { this.id = id; this.cyclicBarrier = cyclicBarrier; } @Override public void run() { System.out.println("员工" + id + "现在从大门出发,前往自行车驿站"); try { Thread.sleep((long) (Math.random() * 10000)); System.out.println("员工" + id + "到了自行车驿站,开始等待其他人到达"); cyclicBarrier.await(); System.out.println("员工" + id + "已经骑车出发,前往终点"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }} Lock是一种更高级的同步机制,它提供了与synchronized方法类似的功能,但具有更高的灵活性。Lock可以配置为公平锁、非公平锁或重入锁等。
public class LockDemo { private static Lock lock = new ReentrantLock(); // 使用可重入锁 public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 3; i++) { new Thread(new Runnable() { @Override public void run() { try { lock.lock(); // 获取锁 System.out.println("线程" + Thread.currentThread().getName() + "进入了同步区域"); Thread.sleep(1000); // 模拟耗时操作 System.out.println("线程" + Thread.currentThread().getName() + "离开了同步区域"); lock.unlock(); // 释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }} Condition是一种基于对象的条件等待机制,它与Lock结合使用,提供更灵活的同步控制。Condition允许线程在获得锁的情况下等待某些条件成立,否则进入等待状态。
public class ConditionDemo { private static Lock lock = new ReentrantLock(); private static Condition condition = lock.newCondition(); public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 3; i++) { new Thread(new Runnable() { @Override public void run() { try { lock.lock(); // 获取锁 System.out.println("线程" + Thread.currentThread().getName() + "进入了同步区域"); condition.await(); // 等待条件成立 System.out.println("线程" + Thread.currentThread().getName() + "通过了条件等待"); lock.unlock(); // 释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }} 以上是Java多线程编程中常用的多线程控制工具的简要介绍。每种工具都有其适用的场景和特点,选择合适的工具能够更好地实现多线程编程中的同步与协作需求。在实际开发中,需要根据具体的业务需求选择合适的多线程控制工具,并正确地使用这些工具来保证程序的正确性和高效性。
转载地址:http://mywwz.baihongyu.com/