Java并发--线程计数器

多线程通信(二)线程阻塞与多线程计数器 一、介绍: 1、java为顺序执行代码,如 package com.demo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @RequestMapping("/test" 阅读详情

Java中经常存在以下的需求,启动多个相同或者不同的线程,主线程需要等待所有的线程执行完才继续往下执行

要实现上面的需求,基本的思路: 创建一个计数器, 来记录线程的执行

有两种实现方法

方法1:

使用锁和计数器:需要有一个对象锁,作用一:保证这个计数器的线程安全,作用二:阻塞主线程,等待所有线程执行完再来唤醒主线程继续执行

方法2:

使用Java线程包中的CountDownLatch:不需要加锁, 不需要wait notify这么复杂

方法1:

package com.yaya.thread.threadCount.count;

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

public class TestCount {

	int count = 0;

	int total = 0;

	Object object = new Object();

	void testCount() {
		total = 10;
		ExecutorService pool = Executors.newFixedThreadPool(5);
		for (int i = 0; i < 10; i++) {
			final int j = i;
			Runnable runnable = new Runnable() {

				@Override
				public void run() {
					// TODO Auto-generated method stub
					try {
						System.out.println("runnalbe:" + j);
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} finally {
						synchronized (object) {
							count++;
							if (count == total) {
								object.notify();
							}
						}
					}

				}

			};
			pool.execute(runnable);

		}
		synchronized (object) {
			if (count != total) {
				try {
					object.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		System.out.println("end");
		pool.shutdown();
	}

	public static void main(String[] args) {
		TestCount testCount = new TestCount();
		testCount.testCount();
	}

}

方法2: CountDownLatch

package com.yaya.thread.threadCount.countDownLatch;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;

import com.yaya.thread.future.ThreadPoolUtil;

public class TestCountDownLatch {

	static CountDownLatch count = null;
	
	public void testRunnalbe(){
		List<String> list = new ArrayList<String>();
		for (int i = 1; i <= 10; i++) {
			list.add("list" + i);
		}
		count = new CountDownLatch(list.size());

		List<Runnable> runnables = new ArrayList<Runnable>();

		for (int i = 0; i < list.size(); i++) {
			final String listName = list.get(i);
			Runnable runnable = new TestRunnable1(listName, count);
			runnables.add(runnable);
		}

		try {
			ThreadPoolUtil.exeRunnableList(runnables);

		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
		try {
			count.await();
			System.out.println("end");
			ThreadPoolUtil.shutDown(true);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	
	public void testDifferentRunnalbes(){
		List<String> list = new ArrayList<String>();
		for (int i = 1; i <= 10; i++) {
			list.add("list" + i);
		}
		count = new CountDownLatch(list.size()*2);

		List<Runnable> runnables = new ArrayList<Runnable>();

		for (int i = 0; i < list.size(); i++) {
			final String listName = list.get(i);
			Runnable runnable = new TestRunnable1(listName, count);
			runnables.add(runnable);
		}
		
		for (int i = 0; i < list.size(); i++) {
			final String listName = list.get(i);
			Runnable runnable = new TestRunnable2(listName, count);
			runnables.add(runnable);
		}

		try {
			ThreadPoolUtil.exeRunnableList(runnables);

		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
		try {
			count.await();
			System.out.println("end");
			ThreadPoolUtil.shutDown(true);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		TestCountDownLatch  testCountDownLatch  = new TestCountDownLatch();
		testCountDownLatch.testDifferentRunnalbes();
	}

}
package com.yaya.thread.threadCount.countDownLatch;

import java.util.concurrent.CountDownLatch;

public class TestRunnable2 implements Runnable {

	String appid;

	CountDownLatch count;

	public TestRunnable2(String appid, CountDownLatch count) {
		super();
		this.appid = appid;
		this.count = count;
	}

	@Override
	public void run() {
		System.out.println("task" + this.appid + "开始");
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("task" + this.appid + "睡了3s");
		count.countDown();

	}

}

package com.yaya.thread.future;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolUtil {

	// 线程池
	private static ThreadPoolExecutor threadPool;

	// 线程池核心线程数
	private static final int CORE_POOL_SIZE = 5;

	// 线程池最大线程数
	private static final int MAX_POOL_SIZE = 10;

	// 额外线程空状态生存时间
	private static final int KEEP_ALIVE_TIME = 10000;

	private static final int CANCEL_TASK_TIME = 20;

	private ThreadPoolUtil() {

	}

	static {
		threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
				new LinkedBlockingQueue<>(30), new ThreadFactory() {
					private final AtomicInteger integer = new AtomicInteger();

					@Override
					public Thread newThread(Runnable r) {
						return new Thread(r, "mock thread:" + integer.getAndIncrement());
					}
				});
	}

	/**
	 * 从线程池中抽取线程,执行指定的Runnable对象
	 * 
	 * @param runnable
	 */
	public static void execute(Runnable runnable) {
		threadPool.execute(runnable);
	}

	/**
	 * 批量执行 Runnable任务
	 * 
	 * @param runnableList
	 */
	public static void exeRunnableList(List<Runnable> runnableList) {
		for (Runnable runnable : runnableList) {
			threadPool.execute(runnable);
		}
	}

	/**
	 * 从线程池中抽取线程,执行指定的Callable对象
	 * 
	 * @param callable
	 * @return 返回执行完毕后的预期结果
	 */
	public static Future exeCallable(Callable<String> callable) {
		return threadPool.submit(callable);
	}

	/**
	 * 批量执行 Callable任务
	 * 
	 * @param callableList
	 *            callable的实例列表
	 * @return 返回指定的预期执行结果
	 */
	public static List<Future<String>> exeCallableList(List<Callable<String>> callableList) {
		List<Future<String>> futures = null;
		try {
			for (Callable<String> task : callableList) {
				threadPool.submit(task);
			}
			futures = threadPool.invokeAll(callableList);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return futures;
	}

	/**
	 * 批量执行 Callable任务, 但不等待执行完
	 * 
	 * @param callableList
	 *            callable的实例列表
	 * @return 返回指定的预期执行结果
	 */
	public static void exeCallableListNoReturn(List<Callable<String>> callableList) {
		for (Callable<String> task : callableList) {
			threadPool.submit(task);
		}

	}

	/**
	 * 中断任务的执行
	 * 
	 * @param isForceClose
	 *            true:强制中断 false:等待任务执行完毕后,关闭线程池
	 */
	public static void shutDown(boolean isForceClose) {
		if (isForceClose) {
			threadPool.shutdownNow();
		} else {
			threadPool.shutdown();
		}
	}

	/**
	 * 若超出CANCEL_TASK_TIME的时间,没有得到执行结果,则尝试中断线程
	 * 
	 * @param future
	 * @return 中断成功,则返回true 否则返回false
	 */
	public static boolean attemptCancelTask(Future future) {
		boolean cancel = false;
		try {
			future.get(CANCEL_TASK_TIME, TimeUnit.MINUTES);
			cancel = true;
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		} catch (TimeoutException e) {
			cancel = future.cancel(true);
			e.printStackTrace();
		}
		return cancel;
	}

}


利用Java中的AtomicInteger实现高并发环境下的线程安全计数器 AtomicInteger`是Java并发包中一个非常实用的工具类,它通过硬件级别的CAS指令,为开发者提供了一种高效、线程安全的整数更新方案。在实现高并发计数器这类需求时,它往往是优于传统同步锁的首选。然而,开发者也需要清楚其适用场景和潜在限制,对于更复杂的并发控制,可能需要结合使用`ConcurrentHashMap`、`LongAdder`(适用于高并发写多读少的求和场景)等其他并发组件来构建健壮的高性能应用。 阅读详情

相关推荐

中介效应、调节效应与交互效应:从概念辨析到统计建模全指南

在社会科学与数据分析研究中,理解变量之间的因果关系与条件性影响是核心任务之一。回归分析作为最基础的统计工具,常被用于探索自变量对因变量的作用机制,而中介效应与调节效应则分别回答了“如何影响”与“何时影响不同”的深层问题。中介效应通过路径分析拆解因果链条,揭示内部的传导机制;调节效应则借助交互项识别影响的边界条件。Bootstrap法已成为检验间接效应的主流手段,而简单斜率分析则让调节作用的模式更加直观。无论是用户研究、医学统计还是产品数据分析,掌握这些模型都能帮助研究者构建更具解释力的实证框架。本文基于大量

weixin_29051149的博客 330

并发编程--并发工具类

一、CountDownLatch 1.概述 CountDownLatch可以使一个获多个线程等待其他线程各自执行完毕后再执行。 CountDownLatch 定义了一个计数器,和一个阻塞队列, 当计数器的值递减为0之前,阻塞队列里面的线程处于挂起状态,当计数器递减到0时会唤醒阻塞队列所有线程,这里的计数器是一个标志,可以表示一个任务一个线程,也可以表示一个倒计时器,CountDownLatch可以解决那些一个或者多个线程在执行之前必须依赖于某些必要的前提业务先执行的场景。 2.常用方法 Coun

zhang09090606的博客 357

最新打赏系统打赏源码麒麟最新打赏源码喜盈门打赏知识付费课程教程直播讲解

打赏源码打赏系统

qq_41095398的博客 2028

JAVA多线程同步计数器

java多线程同步计算器,包含CountDownLatch、CyclicBarrier及Semaphore

qq_34434565的博客 4192

Proteus仿真实战:用AT89C51+L298N搭建直流电机PID调速系统(附完整工程文件)

本文详细介绍了使用Proteus仿真平台结合AT89C51单片机和L298N驱动模块搭建直流电机PID闭环调速系统的全过程。从硬件选型、电路连接到PID算法实现与参数整定,提供了完整的开发指南和工程文件,帮助读者快速掌握闭环调速系统的设计与调试技巧。

weixin_28724661的博客 447

ASPICE标准快速掌握「1.1. 简介」

ASPICE是汽车软件过程改进能力模型(Automotive SPICE,Automotive - Software Process Improvement and Capability dEtermination)的缩写,是一种针对汽车软件开发过程的国际标准。该标准旨在帮助汽车制造商和供应商改进其软件开发过程,以确保其软件产品的质量和安全性。需要做什么为什么要做技术上的依赖性是什么。

雪云飞星的博客 2291

多线程并发之CountDownLatch阻塞等待

latch则是门闩、锁住的含义。整体含义可以理解为倒数的门栓。的作用也是如此,在构造的时候需要传入一个整数n(必须>0),在这个整数“倒数”到0之前,主线程需要等待在门口,而这个“倒数”过程则是由各个执行线程驱动的,每个线程执行完一个任务“倒数”一次。总结来说,的作用就是等待其他的线程都执行完任务,必要时可以对各个任务的执行结果进行汇总,然后主线程才继续往下执行。主要有两个方法:和。方法用于使计数器减一,其一般是执行任务的线程调用,方法则使调用该方法的线程处于等待状态,其一般是主线程调用。......

Lifelong learning 7954

【k8s故障处理篇】calico-node启动失败“Felix is not live: Get “http://localhost:9099/liveness” 解决办法(V1.30.3版本)

【k8s故障处理篇】calico-node启动失败“Felix is not live: Get “http://localhost:9099/liveness” 解决办法(V1.30.3版本)

jks212454的博客 1090

CountDownLatch(线程计数器)

CountDownLatch(线程计数器) CountDownLatch 类位于 java.util.concurrent 包下,利用它可以实现类似计数器的功能。比如有一个任务 A,它要等待其他 4 个任务执行完毕之后才能执行,此时就可以利用 CountDownLatch来实现这种功能了。 特点 countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执

qq_43203949的博客 917

小秋SLAM入门实战ubuntu所有文章汇总

ubuntu 终端如何停止快速打印的输出以及恢复命令 ubuntu 终端如何快速打开当前路径下的图形化窗口界面? killall -9用途用法 ps -xu | grep这个命令的用途 linux 下 top命令显示的是内存是堆内存吗? zip分割和合并 关闭除当前 GNOME 终端窗口以外的所有其他 GNOME 终端窗口 如何在安装系统后设置短密码 【如何使用getrusage获取消耗的CPU时间和进程使用的最大物理内存】 【webots安装使用教程】 Linux系统下查看当前运行的进程和线程的几种方法

小秋 AI SLAM 入门实战教程 1400

【NVIDIA】Jetson Orin Nano系列:烧写Ubuntu22.04

Jeson Orin Nano系列:烧写Ubuntu22.04 电脑主机可以是Ubuntu20.04

郭老二 4894

java并发学习之线程安全的计数器

线程安全的计数器实现原理简介: 在java中volatile关键字可以保证共享数据的可见性,它会把更新后的数据从工作内存刷新进共享内存,并使其他线程中工作内存中的数据失效,进而从主存中读入最新值来保证共享数据的可见性,实现线程安全的计数器通过循环CAS操作来实现。就是先获取一个旧期望值值,再比较获取的值与主存中的值是否一致,一致的话就更新,不一致的话接着循环,直到成功为止. 具体代码实现 ...

qq_37520037的博客 436

silero-vad 训练自己的数据

silero-vad 训练自己的数据

jacke121的专栏 815

java多线程并发之使用CAS实现线程安全的计数器

例示代码如下: package com.company.cas; //使用CAS实现一个线程安全的计数器 public class CASTest { public static void main(String[] args) { CASCounter casCounter=new CASCounter(); for (int i = 0; i < 100; i++) { new Thread(new Runnable() {

qq_43538170的博客 295

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

JAVA模拟高并发及多线程计数器

1、多线程高并发模拟实现可采用闭锁CountDownLatch,设置对应线程数的CountDownLatch,达到就绪条件后会多线程统一执行。这里只是单机模拟,因为线程采用抢占式执行方式,并不能完全模拟统一同时执行。 2、多线程计数器可采用悲观锁CAS实现类AtomicInteger等原子操作方法实现。 import java.util.concurrent.CountDownLatch; ...

endcy的博客 2782

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

java的多线程并发计数器,Java核心-多线程-并发控制器-CountDownLatch倒数计数器

1.基本概念CountDownLatch,中文名倒数计数器,jdk并发工具包中一个并发控制器,它抽象了一个常见的多线程并发场景,开发人员使用它可以写出同时兼顾线程安全性与高效率的代码。2.抽象模型相当于是一种进化版本的等待/通知机制,它可以的实现的是一个或多个工作线程完成任务后通知一个或多个等待线程开始工作,jdk中的await/notify、notifyAll是一个工作线程完成任务通知一个等待线...

weixin_39605345的博客 358

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

采用Java的concurrent包里面的CountDownLatch具有原子操作的计数器,支持并发多线程操作

场景 在高并发多线程的场景中,当一个任务想要往下执行,但必须要等到其他的多个任务执行完毕后,才可以继续往下执行,如何处理呢? 可以试试,Java的concurrent包里面的CountDownLatch,具有原子操作的计数器,支持并发多线程操作。 比如,T想要继续往下执行的任务(调用一个CountDownLatch对象B的await()方法),必须等到其他的任务T1,T2,T3执行完自己的任务后(其他的任务T1,T2,T3调用同一个CountDownLatch对象B的countDown()方法),T调

阿啄debugIT 568

java并发:线程同步机制之计数器&Exechanger

简单来说: CyclicBarrier回环栅栏表示:一组线程互相等待,共同完成。 CountDownlatch线程计数器:当所以线程完成后,才继续执行任务 Semaphore 信号量:只能同时有几个访问数,释放一个加一个 Exchanger 交换:2个线程阻塞在exchanger方法上,然后继续执行 第一节 CountDownLatch (1)初识CountDownLatc...

qq654207743的博客 450

解决Java多线程并发的计数器问题

import java.util.concurrent.atomic.AtomicInteger; public class Counter { public static int count = 0; static AtomicInteger atomic = new AtomicInteger(0); public synchronized static void inc(

yansong_8686的专栏 1万+

java多线程计数器_java并发:线程同步机制之计数器&Exechanger

第一节 CountDownLatch(1)初识CountDownLatch(2)详述CountDownLatchCountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1,当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。CountDownLatch中主要方法如下:public C...

weixin_42131541的博客 552

java 异步计数器_Java并发编程中级篇(三):使用CountDownLatch控制多线程并发等待...

你是否遇到这这样一种情况,我们要举行一个视频会议,有若干的参会人员,需要等待所有的人员到齐后视频会议才能开始。为了解决这个问题,Java API提供了一个线程同步辅助类CountDownLatch,使用这个辅助类可以让线程等待其它线程完成一组操作后才能执行,否则就一直等待。这个类使用一个整形参数来初始化,这个整形参数代表着等待其他线程的数量,使用await()方法让线程开始等待其他线程执行完毕,每...

weixin_39940182的博客 509

Java并发多线程编程——并发工具类CountDownLatch(线程计数器)

一、CountDownLatch的理解 CountDownLatch属于java.util.concurrent包下; CountDownLatch类使一个线程等待其他线程各自执行完毕后再执行; 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。 二、CountDownLatch类中常用方法 void await() 使当前线程在锁存器倒计数至零之前一直等待,除非线程被

小志的博客 672

Java 用多线程实现11种方式实现亿级高并发计数器

出自: 腾讯课堂 700多分钟干货实战Java多线程高并发高性能实战全集 , 我学习完了之后,我做了个笔记. 需求 在一线大厂的日常开发工作中,我们经常需要对业务平台(系统)\纯技术中间件的相关功能进行高并发\高性能的性能测试 假如说你是架构师,请用多线程相关基础知识实现单机环境下,在3秒内实现1亿的计数,并统计亿级计数的耗时. 上面做法很显然单个线程是很慢的, 你用单个线程在三秒内去实现一亿的计数器,这个肯定是搞不定的,肯定是需要多线程的,多线程跑的话需要统计你多个线程计数耗时是多少,就是说呢多个线程从1

张俊杰 的博客 2990

java的多线程并发计数器_JAVA 8 并发增强(1) 多线程修改某个计数器的方式

Q:如何正确的并发修改一个AtomicLong的值?/* 不同线程检测最大值 */AtomicLong largest = new AtomicLong();long obsvValue = 0;/* 错误的方式,此更新不是原子性的 */largest.set(Math.max(largest.get(), obsvValue));/* 正确的方式,这种方式比锁快 */long oldValue;...

weixin_39576751的博客 295

Java多线程与并发库高级应用之倒计时计数器CountDownLatch

CountDownLatch类是一个倒计时计数器,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数初始化 CountDownLatch。由于调用了countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。 CountDownLatch 是一个通用同步工具,它有很多用途...

ypkobe24的专栏 2603

Java面试题:使用单例模式与双重检查锁定实现一个线程安全的单例类;分析Java中的内存模型及内存溢出问题;利用Java并发工具包实现一个线程安全的计数器

通过以上三道面试题,我们可以全面考察候选人在Java设计模式、内存管理、多线程以及并发工具包等方面的知识和应用能力。在Java编程领域,掌握设计模式、内存管理、多线程以及并发工具包等知识点,对于应对复杂的软件开发任务至关重要。Java并发工具包提供了丰富的并发编程工具,如原子变量、锁、信号量等。本题要求分析Java内存模型,包括堆、栈、方法区等,并探讨内存溢出问题的原因和解决策略。内存溢出的原因(如堆溢出、栈溢出、方法区溢出等)。对Java内存模型的理解不深入,混淆堆和栈的概念。

码农超哥的博客 715
上一篇: Java并发-ThreadPoolExecutor线程池中BlockingQueue的三种实现
下一篇: Java 写一个可以给斗地主玩家随机发牌的程序。
yayaqwl
博客等级 码龄13年 28粉丝 103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值