`
coach
  • 浏览: 386957 次
  • 性别: Icon_minigender_2
  • 来自: 印度
社区版块
存档分类
最新评论

根据cpu情况决定线程运行数量和情况

 
阅读更多
一个线程分配器,根据cpu的负载情况,自动完成对应线程的唤醒或者是等待操作。整个过程是一个平滑的过程,不会因为线程的切换而导致机器负载出线锯齿。

读取Linux系统TOP等指令拿到系统当前负载
package temp.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * @description 节点的cpu 内存 磁盘空间 情况
 * @version 1.0
 * @date 2012-7-11
 */
public class NodeLoadView
{
	/**
	 * 获取cpu使用情况
	 * @return
	 * @throws Exception
	 */
	public double getCpuUsage() throws Exception
	{
		double cpuUsed = 0;
		Runtime rt = Runtime.getRuntime();
		Process p = rt.exec("/usr/bin/uptime");// 调用系统的"top"命令
		String[] strArray = null;
		BufferedReader in = null;
		try
		{
			in = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String str = null;
			while ((str = in.readLine()) != null)
			{
				strArray = str.split("load average: ");
				strArray = strArray[1].split(",");
				cpuUsed = Double.parseDouble(strArray[0]);
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			in.close();
		}
		return cpuUsed;
	}

	/**
	 * 内存监控
	 * @return
	 * @throws Exception
	 */
	public double getMemUsage() throws Exception
	{
		double menUsed = 0;
		Runtime rt = Runtime.getRuntime();
		Process p = rt.exec("top -b -n 1");// 调用系统的"top"命令
		BufferedReader in = null;
		try
		{
			in = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String str = null;
			String[] strArray = null;
			while ((str = in.readLine()) != null)
			{
				int m = 0;
				if (str.indexOf(" R ") != -1)
				{// 只分析正在运行的进程,top进程本身除外 &&
					//
					// System.out.println("——————3—————–");
					strArray = str.split(" ");
					for (String tmp : strArray)
					{
						if (tmp.trim().length() == 0)
							continue;
						if (++m == 10)
						{
							// 9)–第10列为mem的使用百分比(RedHat 9)
							menUsed += Double.parseDouble(tmp);
						}
					}
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			in.close();
		}
		return menUsed;
	}

	/**
	 * 获取磁盘空间大小
	 * @return
	 * @throws Exception
	 */
	public double getDeskUsage() throws Exception
	{
		double totalHD = 0;
		double usedHD = 0;
		Runtime rt = Runtime.getRuntime();
		Process p = rt.exec("df -hl");// df -hl 查看硬盘空间
		BufferedReader in = null;
		try
		{
			in = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String str = null;
			String[] strArray = null;
			while ((str = in.readLine()) != null)
			{
				int m = 0;
				// if (flag > 0) {
				// flag++;
				strArray = str.split(" ");
				for (String tmp : strArray)
				{
					if (tmp.trim().length() == 0)
						continue;
					++m;
					// System.out.println("—-tmp—-" + tmp);
					if (tmp.indexOf("G") != -1)
					{
						if (m == 2)
						{
							// System.out.println("—G—-" + tmp);
							if (!tmp.equals("") && !tmp.equals("0"))
								totalHD += Double.parseDouble(tmp.substring(0, tmp.length() - 1)) * 1024;
						}
						if (m == 3)
						{
							// System.out.println("—G—-" + tmp);
							if (!tmp.equals("none") && !tmp.equals("0"))
								usedHD += Double.parseDouble(tmp.substring(0, tmp.length() - 1)) * 1024;
						}
					}
					if (tmp.indexOf("M") != -1)
					{
						if (m == 2)
						{
							// System.out.println("—M—" + tmp);
							if (!tmp.equals("") && !tmp.equals("0"))
								totalHD += Double.parseDouble(tmp.substring(0, tmp.length() - 1));
						}
						if (m == 3)
						{
							// System.out.println("—M—" + tmp);
							if (!tmp.equals("none") && !tmp.equals("0"))
								usedHD += Double.parseDouble(tmp.substring(0, tmp.length() - 1));
							// System.out.println("—-3—-" + usedHD);
						}
					}
				}
				// }
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			in.close();
		}
		return (usedHD / totalHD) * 100;
	}

	public static void main(String[] args) throws Exception
	{
		NodeLoadView cpu = new NodeLoadView();
		System.out.println("—————cpu used:" + cpu.getCpuUsage() + "%");
		System.out.println("—————mem used:" + cpu.getMemUsage() + "%");
		System.out.println("—————HD used:" + cpu.getDeskUsage() + "%");
		System.out.println("————jvm监控———————-");
		Runtime lRuntime = Runtime.getRuntime();
		System.out.println("————–Free Momery:" + lRuntime.freeMemory() + "K");
		System.out.println("————–Max Momery:" + lRuntime.maxMemory() + "K");
		System.out.println("————–Total Momery:" + lRuntime.totalMemory() + "K");
		System.out.println("—————Available Processors :" + lRuntime.availableProcessors());
	}
}


package temp.util;

import java.util.Map;

import org.apache.log4j.Logger;

/**
 * @description
 * @version 1.0
 * @date 2012-7-11
 */
public class ThreadScheduler
{
	private static Logger logger = Logger.getLogger(ThreadScheduler.class.getName());
	private Map<String, Thread> runningThreadMap;
	private Map<String, Thread> waitingThreadMap;
	private boolean isFinished = false;
	private int runningSize;

	public ThreadScheduler(Map<String, Thread> runningThreadMap, Map<String, Thread> waitingThreadMap)
	{
		this.runningThreadMap = runningThreadMap;
		this.waitingThreadMap = waitingThreadMap;
		this.runningSize = waitingThreadMap.size();
	}

	/**
	 * 开始调度线程
	 * @author zhen.chen
	 * @createTime 2010-1-28 上午11:04:52
	 */
	public void schedule()
	{
		long sleepMilliSecond = 1 * 1000;
		int allowRunThreads = 15;
		// 一次启动的线程数,cpuLoad变大时以此值为参考递减
		int allowRunThreadsRef = 15;
		double cpuLoad = 0;// 0-15
		NodeLoadView load = new NodeLoadView();
		while (true)
		{
			try
			{
				cpuLoad = load.getCpuUsage();
			}
			catch (Exception e1)
			{
				e1.printStackTrace();
			}
			// cpuLoad低 启动的线程多
			allowRunThreads = (int) Math.floor(allowRunThreadsRef - cpuLoad);
			// threads不能为0
			if (allowRunThreads < 1)
			{
				allowRunThreads = 1;
			}
			if (allowRunThreads > allowRunThreadsRef)
			{
				allowRunThreads = allowRunThreadsRef;
			}
			if (logger.isDebugEnabled())
			{
				logger.debug("[ThreadScheduler]running Thread:" + runningThreadMap.size() + "; waiting Thread:" + waitingThreadMap.size() + "; cpu:" + cpuLoad + " allowRunThreads:" + allowRunThreads);
			}
			// 检查等待线程runningSize个线程的情况,满足条件则启动
			for (int x = 0; x < runningSize; x++)
			{
				if (waitingThreadMap.get(x + "") != null)
				{
					if (allowRunThreadsRef <= runningThreadMap.size())
					{
						break;
					}
					synchronized (waitingThreadMap.get(x + ""))
					{
						if (!waitingThreadMap.get(x + "").isAlive())
						{
							waitingThreadMap.get(x + "").start();
						}
						else
						{
							waitingThreadMap.get(x + "").notify();
						}
					}
					runningThreadMap.put(x + "", waitingThreadMap.get(x + ""));
					waitingThreadMap.remove(x + "");
				}
			}
			// 检查runningSize个线程的情况,满足条件则暂停
			for (int x = 0; x < runningSize; x++)
			{
				if (runningThreadMap.size() <= allowRunThreads)
				{
					break;
				}
				if (runningThreadMap.get(x + "") != null)
				{
					synchronized (runningThreadMap.get(x + ""))
					{
						try
						{
							if (runningThreadMap.get(x + "").isAlive())
							{
								runningThreadMap.get(x + "").wait();
							}
							else
							{
								continue;
							}
						}
						catch (InterruptedException e)
						{
							e.printStackTrace();
						}
					}
					waitingThreadMap.put(x + "", runningThreadMap.get(x));
					runningThreadMap.remove(x + "");
				}
			}
			// 全部跑完,返回
			if (waitingThreadMap.size() == 0 && runningThreadMap.size() == 0)
			{
				if (logger.isDebugEnabled())
				{
					logger.debug("[ThreadScheduler] over.total Threads size:" + runningSize);
				}
				this.isFinished = true;
				return;
			}
			// 使主while循环慢一点
			try
			{
				Thread.sleep(sleepMilliSecond);
			}
			catch (InterruptedException e1)
			{
				e1.printStackTrace();
			}
		}
	}

	public boolean isFinished()
	{
		return isFinished;
	}
}


这个类的作用:
  • 1.接收runningThreadMap和waitingThreadMap两个map,里面对应存了运行中的线程实例和等待中的线程实例。
  • 2.读cpu情况,自动判断要notify等待中的线程还是wait运行中的线程。
  • 3.两个map都结束,退出。(必须runningThreadMap内部的Thread自己将runningThreadMap对应的Thread remove掉)


使用:
package temp.util;

import java.util.HashMap;
import java.util.Map;

/**
 * @description
 * @version 1.0
 * @date 2012-7-11
 */
public class TestThread
{
	public static class Runner extends Thread
	{
		public Runner(int j, Map<String, Thread> threadMap)
		{
		}

		public void run()
		{
			// TODO 你的逻辑 完成后需要从threadMap中remove掉
		}
	}

	public static void main(String[] args)
	{
		// 运行中的线程
		Map<String, Thread> threadMap = new HashMap<String, Thread>();
		// 正在等待中的线程
		Map<String, Thread> waitThreadMap = new HashMap<String, Thread>();
		for (int j = 0; j < args.length; j++)
		{
			Thread t = new Runner(j, threadMap);
			waitThreadMap.put(j + "", t);
		}
		ThreadScheduler threadScheduler = new ThreadScheduler(threadMap, waitThreadMap);
		threadScheduler.schedule();
		if (threadScheduler.isFinished() == false)
		{
			// 没能正常结束
		}
	}
}
分享到:
评论

相关推荐

    根据进程ID获取进程的内存使用量,CPU使用率,线程个数据信息

    本文将深入探讨如何根据进程ID获取进程的内存使用量、CPU使用率以及线程个数,这些信息对于诊断系统性能问题、优化应用运行效率以及监控系统健康状态具有极大的价值。 首先,我们来理解“进程ID”(Process ID,PID...

    linux 下 跟踪线程运行情况

    在Linux操作系统中,跟踪线程运行情况是系统管理员和开发者常用的一种诊断和性能优化手段。了解如何有效地监控线程活动对于理解和调试多线程应用程序至关重要。以下是一些关键知识点: 1. **线程基础** - 线程是...

    centos查看系统cpu个数、核心数、线程数

    ### CentOS下查看CPU相关信息 在CentOS环境下,了解系统的CPU配置是进行性能调优和资源管理的基础。本文将详细介绍如何在CentOS系统中查询CPU的...在进行虚拟化时,可以根据物理CPU数量和核心数来优化虚拟机配置等。

    LoadRunner中进程运行和线程运行的区别

    ### LoadRunner中进程运行与线程运行的区别 #### 进程与线程的基本概念 在计算机科学领域,进程和线程都是实现程序并发执行的基本单位。它们之间存在着本质的区别,这些区别不仅体现在技术细节上,而且对软件设计...

    C#线程池 所有线程运行完毕

    线程池的工作原理是:当任务被提交到线程池时,线程池会根据当前系统负载和已有的线程数量,决定是否立即创建新线程执行任务,或者将任务放入队列等待。线程池会维护一个最小和最大线程数,以保持性能与资源消耗的...

    VC++调用大漠插件多线程运行模版

    因此,需要根据具体应用场景和硬件条件合理设计线程数量。 通过以上知识,开发者可以构建出高效稳定的大漠插件多线程运行模版,实现并发处理任务,提高程序执行效率。在实际项目中,务必注意测试和调试,确保线程...

    完美获取 CPU 的 NUMA节点数、CPU插槽个数 、 核心数 、 逻辑处理器数(线程数)、名字、制造商、指令集、主频、等等

    根据 CPU 核心数和线程数选择合适的多线程策略;而了解 CPU 的指令集则有助于优化软件代码,使其更好地利用硬件特性。 总的来说,全面掌握 CPU 的各项参数是提升系统性能的关键步骤,无论是系统管理员还是开发者,...

    delphi 多线程 指定线程数运行例子

    通过这个简单的例子,我们学习了如何在Delphi中创建和管理指定数量的线程。当然,实际应用中,还需要考虑线程同步、资源竞争等问题,例如使用CriticalSection、Mutex等同步原语。此外,还要注意线程间的通信,避免...

    delphi7 多线程测试(40个线程)

    在编程领域,多线程是一种常见且强大的技术,它允许程序同时执行多个任务,从而提高效率和响应性。...在实际项目中,开发者应根据具体情况调整线程数量,平衡并行度和系统资源利用率,以达到最佳性能。

    基于WinSock的多线程CPU资源利用研究.pdf

    每个线程都有自己的执行上下文,CPU会根据线程优先级和调度策略来决定哪个线程应该获取执行权。合理地设计线程数量和任务分配,可以避免过度消耗CPU资源,同时确保程序的响应速度和整体性能。 四、线程池技术 为了...

    Nachos实现id、限制线程数和按优先级调度算法 源码.rar

    然后,优先级调度算法是操作系统中用于决定哪个线程应该获得CPU执行权的一种策略。在Nachos中,`scheduler.cc`和`scheduler.h`很可能是实现这一算法的关键文件。通常,高优先级的线程会被优先调度,以保证对时间敏感...

    线程——基本线程的应用和线程调用控件

    - 为避免频繁创建和销毁线程带来的开销,线程池预先创建一定数量的线程,任务到来时直接从池中获取线程执行,完成后归还到池中。 - Java的`ExecutorService`和`ThreadPoolExecutor`,C#'s `ThreadPool`都是线程池...

    C# 如何挂起线程、休眠线程和终止线程(源码例)

    休眠线程是一种避免线程过度占用CPU资源的好方法,尤其在需要定时执行或者需要其他线程执行特定任务时。 3. **终止线程**: 终止线程是指强制结束线程的执行,使其不再继续运行。在C#中,直接使用`Thread.Abort()`...

    CPU-ZCPU运行测试

    它能显示CPU的基本信息,包括制造商、型号、频率、核心数量、线程数量、制造工艺、缓存大小等。例如,如果你的电脑使用的是Intel i7处理器,CPU-Z会展示该处理器的具体型号(如i7-10700K),主频、睿频速度,以及L1...

    C#线程详解,单线程,多线程,线程管理

    每个线程都有一个优先级,用于决定调度器如何分配CPU时间。然而,调整线程优先级并不总是能提高性能,有时甚至会导致反效果,因此应谨慎使用。 ### 4. 并发问题 - 死锁:两个或更多线程相互等待对方释放资源,导致...

    车牌号码识别及多线程实现线程数量从1~6-源代码

    当线程数量增加时,可能会增加CPU的使用率,提高处理速度,但过多的线程也可能导致资源竞争和上下文切换开销,反而降低效率。 “源代码能直接在VS2008中运行”表明这个项目是用C++或.NET框架开发的,因为Visual ...

    进程与线程的生动形象理解

    这反映了单个CPU一次只能运行一个任务的情况。 3. **进程与车间**:进程可以类比为工厂的车间,代表着CPU能够处理的单个任务。在任何时刻,CPU都在运行一个进程,而其他进程则处于非运行状态。 4. **线程与工人**...

    解决python线程卡死的问题

    - 查看线程的`%CPU`和`%MEM`值。如果某一线程的这两项指标都接近于0,则说明该线程很可能已经卡死。 ##### 2. 打日志定位问题 除了使用`top`命令之外,还可以通过在程序中添加日志来进一步定位问题。特别是对于I/...

    多线程测试(是多线程的测试,对学习多线程的朋友有用)

    3. 资源消耗测试:分析多线程运行时内存、CPU和其他资源的使用情况。 4. 并发测试:评估程序在高并发场景下的稳定性和响应能力。 5. 错误处理和异常测试:确保在多线程环境下程序能够正确捕获和处理异常。 总之,多...

Global site tag (gtag.js) - Google Analytics