多线程编程_CountDownLatch
CountDownLatch是JAVA提供在java.util.concurrent包下的一个辅助类,可以把它看成是一个计数器,其内部维护着一个count计数,只不过对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器,CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CounDownLatch对象的cutDown()方法,来使计数减1;如果调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到别人通过cutDown方法,将计数减到0,才可以继续执行。
利用这种性质可以做一些事情
简单举几种简单的例子
1.需要开多线程执行,等所有的执行完成之后。在做其他的事情。
2.某个线程执行的时间不确定,我想等5秒之后如果,如果线程还没执行完,处理其他的逻辑
1.需要开多线程执行,等所有的执行完成之后。在做其他的事情。
第一种可以模拟,赛跑比赛,每个运动员是一个线程。所有的线程到达终点比赛结束。
import java.util.concurrent.CountDownLatch; public class Sample {
/**
* 计数器,用来控制线程
* 传入参数2,表示计数器计数为2
*/
private final static CountDownLatch mCountDownLatch = new CountDownLatch(2); /**
* 示例工作线程类
*/
private static class WorkingThread extends Thread {
private final String mThreadName;
private final int mSleepTime;
public WorkingThread(String name, int sleepTime) {
mThreadName = name;
mSleepTime = sleepTime;
} @Override
public void run() {
System.out.println("[" + mThreadName + "] started!");
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
mCountDownLatch.countDown();
System.out.println("[" + mThreadName + "] end!");
}
} /**
* 示例线程类
*/
private static class SampleThread extends Thread { @Override
public void run() {
System.out.println("[SampleThread] started!");
try {
// 会阻塞在这里等待 mCountDownLatch 里的count变为0;
// 也就是等待另外的WorkingThread调用countDown()
mCountDownLatch.await();
} catch (InterruptedException e) { }
System.out.println("[SampleThread] end!");
}
} public static void main(String[] args) throws Exception {
// 最先run SampleThread
new SampleThread().start();
// 运行两个工作线程
// 工作线程1运行5秒
new WorkingThread("WorkingThread1", 5000).start();
// 工作线程2运行2秒
new WorkingThread("WorkingThread2", 2000).start();
}
}
结果如下
[SampleThread] started!
[WorkingThread1] started!
[WorkingThread2] started!
[WorkingThread2] end!
[WorkingThread1] end!
[SampleThread] end!
2.某个线程执行的时间不确定,我想等2秒之后如果,如果线程还没执行完,处理其他的逻辑
final CountDownLatch latch = new CountDownLatch(1);
final File outFile = new File(dir, imageName);
reuslt.path=outFile.getAbsolutePath();
reuslt.bitmap=bitmap;
Thread sleepThread = new Thread() {
@Override
public void run() {
super.run();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
reuslt.result=false;
reuslt.type=Reuslt.THREAD_SLEEP;
latch.countDown();
}
};
Thread saveThread = new Thread() {
@Override
public void run() {
super.run();
boolean result=BitmapUtils.saveBitmapWithQuality(bitmap, outFile.getPath(), picQuality);
reuslt.result=result;
reuslt.type=Reuslt.THREAD_SAVE;
latch.countDown();
}
}; sleepThread.start();
saveThread.start(); try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//TODO samethings
public static List<List<ProcessInfo>> getRunningProcessListTheadPool(final Context context) {
if (DEBUG) {
Log.i(TAG, "getRunningProcessListTheadPool");
}
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
final PackageManager packageManager=context.getPackageManager();
long time = 0l;
if (DEBUG) {
time = System.currentTimeMillis();
}
final CopyOnWriteArrayList<ProcessInfo> processList = new CopyOnWriteArrayList<ProcessInfo>();
final ArrayList<ProcessInfo> whiteListProcess = new ArrayList<ProcessInfo>();
List<List<ProcessInfo>> returnList = new ArrayList<List<ProcessInfo>>();
returnList.add(processList);
returnList.add(whiteListProcess); List<RunningAppProcessInfo> allRunningProcessesList = null;
try {
allRunningProcessesList = activityManager.getRunningAppProcesses();
} catch (Exception e) {
if (DEBUG) {
Log.e(TAG, "系统出错 ActivityManager.getRunningAppProcesses Exception");
}
} //5.0以上有部分手机getRunningAppProcesses只能获得当前运行的自己的程序
if (!BoostRunningProcessUtil.isRunningAppProcessesEnable(allRunningProcessesList)) {
allRunningProcessesList = GetRunningProcessUtil.getRunningAppProcesses(activityManager, packageManager);
if (DEBUG) {
Log.e(TAG, "5.0以上有部分手机 打印获取的程序列表" );
for(RunningAppProcessInfo item:allRunningProcessesList){
Log.i(TAG,item.processName);
}
Log.e(TAG, "5.0以上有部分手机getRunningAppProcesses只能获得当前运行的自己的程序=");
}
} if (allRunningProcessesList == null || allRunningProcessesList.isEmpty()) {
return returnList;
} List<RunningServiceInfo> runningServicesTemp = null;
try {
runningServicesTemp = activityManager.getRunningServices(500);
} catch (Exception e) {
//java.lang.NullPointerException: Attempt to read from field
//'android.content.ComponentName com.android.server.am.ServiceRecord.name' on a null object reference
//at android.os.Parcel.readException(Parcel.java:1546)
//at android.os.Parcel.readException(Parcel.java:1493)
// at android.app.ActivityManagerProxy.getServices(ActivityManagerNative.java:3068)
if (DEBUG) {
Log.e(TAG, "系统出错 ActivityManager.getRunningServices Exception");
}
} if (runningServicesTemp == null) {
runningServicesTemp = new ArrayList<RunningServiceInfo>(0);
}else{
if (DEBUG) {
Log.e(TAG, "获取到的运行的service size"+runningServicesTemp.size() );
for(RunningServiceInfo item:runningServicesTemp){
Log.i(TAG,item.process);
}
}
} final List<RunningServiceInfo> runningServices = runningServicesTemp;
int size = allRunningProcessesList.size();
// 开始的倒数锁
final CountDownLatch begin = new CountDownLatch(1);
// 结束的倒数锁
final CountDownLatch end = new CountDownLatch(size);
final ExecutorService exec = BoosterExecutorsPro.newFixedThreadPool("getRunningProcessListTheadPool",6); final List<String> mobiProducts = Arrays.asList(SysClearEnv.MOBIMAGICP_PRD);
final String myPkg=context.getPackageName();
for (RunningAppProcessInfo item : allRunningProcessesList) {
//////////////////////////////////////////////////////////////////////
final RunningAppProcessInfo runningAppProcessInfo = item;
Runnable run = new Runnable() {
public void run() {
try {
// 等待.如果当前计数为零,则此方法立即返回。
begin.await(); /*********************************************************************************/
if (runningAppProcessInfo == null) {
return;
}
final String processName = runningAppProcessInfo.processName;
if (TextUtils.isEmpty(processName)) {
return;
} long singleStartTime = 0;
if (DEBUG) {
singleStartTime = System.currentTimeMillis();
Log.d(TAG, processName + " " + Arrays.toString(runningAppProcessInfo.pkgList)
+ " importance:" + runningAppProcessInfo.importance);
} // 获取进程相关的服务
String[] processServices = LoadProcessUtils.getProcessServices(processName, runningServices); /*
* 由于 Android 系统中一个进程可能是由多个不同的包共享的,试过把这些包都显示出来,发现比如说设置的进程,里面包含了
* Status Bar,
* 设置,设置存储三个包,它们的图标都一样,用户就会提出疑问说为什么有三个一样的,没办法,后面就只显示其中一个包
* 进程中如果没有package,则默认可杀
*/
String[] packageList = (runningAppProcessInfo.pkgList == null) ? new String[] { processName }
: runningAppProcessInfo.pkgList; //根据PackageName处理
for (String packageName : packageList) { long time = System.currentTimeMillis(); PackageInfo packageInfo = null;
try {
if (SysClearEnv.PACKAGE_CACHE) {
packageInfo = getPackageInfo(packageManager, packageName);
} else {
packageInfo = packageManager.getPackageInfo(packageName, 0);
} if (packageInfo != null) {
if (!TextUtils.isEmpty(packageInfo.sharedUserId)) {
flag = ConfigLoader.getInstance(context).queryFilter(
ConfigLoader.SHARED_USER_ID, packageInfo.sharedUserId);
} }
} catch (Exception e) {
//NameNotFoundException, Package manager has died
if (DEBUG) {
Log.e(TAG, "getPackageInfo", e);
}
}
ProcessInfo processInfo = LoadProcessUtils.createProcessInfo(context, packageInfo,
runningAppProcessInfo, packageName, processName, processServices); // 当应用有多个进程时,将每个进程内存累加;
boolean unAddFlag = true;
synchronized (processList) {
for (ProcessInfo existProcessInfo : processList) {
if (packageName.equals(existProcessInfo.packageName)) {
// 取最小的一个进程importance作为合并进程的importance// 修正读到的flag被合并后消失的情况// 合并服务// 合并PID
unAddFlag = false;
break;
}
} if (unAddFlag) { processList.add(processInfo);
}
}
} /*********************************************************************************/
} catch (Exception e) {
if (DEBUG) {
Log.e(TAG, "====getRunningProcessList有误!!!!====", e);
}
} finally {
// 每个 线程执行完成end就减一
end.countDown();
} }
};
exec.submit(run);
//////////////////////////////////////////////////////////////////////
}
// begin减一
begin.countDown();
// 等待结束
try {
end.await();
} catch (Exception e) { }
exec.shutdown(); return returnList;
}
多线程编程_CountDownLatch的更多相关文章
- Web Worker javascript多线程编程(一)
什么是Web Worker? web worker 是运行在后台的 JavaScript,不占用浏览器自身线程,独立于其他脚本,可以提高应用的总体性能,并且提升用户体验. 一般来说Javascript ...
- Web Worker javascript多线程编程(二)
Web Worker javascript多线程编程(一)中提到有两种Web Worker:专用线程dedicated web worker,以及共享线程shared web worker.不过主要讲 ...
- windows多线程编程实现 简单(1)
内容:实现win32下的最基本多线程编程 使用函数: #CreateThread# 创建线程 HANDLE WINAPI CreateThread( LPSECURITY_ATTRIBUTES lpT ...
- Rust语言的多线程编程
我写这篇短文的时候,正值Rust1.0发布不久,严格来说这是一门兼具C语言的执行效率和Java的开发效率的强大语言,它的所有权机制竟然让你无法写出线程不安全的代码,它是一门可以用来写操作系统的系统级语 ...
- windows多线程编程星球(一)
以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...
- Java多线程编程核心技术---学习分享
继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...
- python多线程编程
Python多线程编程中常用方法: 1.join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join( ...
- 浅述WinForm多线程编程与Control.Invoke的应用
VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...
- Java—多线程编程
一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程.一个线程不能独立的存 ...
随机推荐
- ASP.NET常用数据绑定控件优劣总结
本文的初衷在于对Asp.net常用数据绑定控件进行一个概览性的总结,主要分析各种数据绑定控件各自的优缺点,以便在实际的开发中选用合适的控件进行数据绑定,以提高开发效率. 因为这些数据绑定控件大部分都已 ...
- Docker基本使用(二) Hello World
Docker 允许你在容器内运行应用程序, 使用 docker run 命令来在容器内运行一个应用程序. 输出Hello world runoob@runoob:~$ docker run ubunt ...
- Kafka 练习题
一.选择题 Kafka服务器默认能接收的最大消息是多大? (单选) A A:1M B:10M C:100M D:没有大小限制,因为支持大数据 2.Kafka的特性(多选) ABCD A:高吞吐量.低 ...
- AB二进制
Description 若将一个正整数化为二进制数,在此二进制数中,我们将数字1的个数多于数字0的个数的这类二进制数称为A类数,否则就称其为B类数. 例如: (13)10=(1101)2 ...
- sql_trace基本用法
sql_trace是oracle提供的一个非常好的跟踪工具,主要用来检查数据库的异常情况,通过跟踪数据库的活动,找到有问题的语句. 一.概述: SQL_TRACE是Oracle的一个非常强大的工 ...
- CF567E President and Roads
\(\color{#0066ff}{ 题目描述 }\) 给出一个有向图,从起点走到终点(必须走最短路),问一条边是否一定会被经过,如果不经过它,可以减小它的多少边权使得经过它(边权不能减少到0) \( ...
- DP【洛谷P2363】马农
[洛谷P2363]马农 题目描述 在观看完战马检阅之后,来自大草原的两兄弟决心成为超级"马农",专门饲养战马. 兄弟两回到草原,将可以养马的区域,分为N*N的单位面积的正方形,并实 ...
- 文件上传之form表单篇
form表单上传文件 作为本系列的最后一篇,也是楼主知道的第三种文件上传的方式--隆重推出Form表单 这是最传统的上传文件,提交数据的方式 Html: <form action="/ ...
- CF580B Kefa and Company 尺取法
Kefa wants to celebrate his first big salary by going to restaurant. However, he needs company. Kefa ...
- Java内存区域与内存溢出异常---对象的内存布局和对象的访问定位
对象的内存布局 在HotSpot虚拟机中,对象在内存中的存储布局可以划分为三个区域:对象头,实例数据,对齐填充. 对象头包括两部分信息:第一部分用于存储对象自身的运行时数据,如哈希码,GC分代 ...