1. 项目目标
统计磁盘某个文件目录下子目录、子文件所占空间的大小
通过曲线图实时展示 CPU 占有率
掌握多线程编程技术
深入理解树的遍历方法

2. 项目使用技术栈与平台
所用技术:javaSE/javafx
平台与环境:windows 10/jdk1.8/idea

3. 项目功能
显示 CPU 占有率
文件目录扫描

4. 项目演示

显示 CPU 占有率

oss 可以替代mongodb_文件目录


文件目录扫描

oss 可以替代mongodb_文件目录_02


5. 项目分模块讲解思路

项目总体模块框图

创建主程序

fxml 描述 UI

CPU 占有率 Tab 页设计

磁盘扫描 Tab 页设计

Controller 模块

系统资源获取模块

文件目录扫描模块5. 项目实现细节
5.1 项目总体模块框图

OS Monitor 项目结构分为两部分:UI 部分和逻辑部分。

UI 部分包括:主程序、磁盘空间扫描 Tab 页、CPU 占有率 Tab 页、Controller。UI 部分是通过 javafx

来实现。

逻辑部分包括:系统资源获取、文件目录扫描。系统资源是通过 OperatingSystemMXBean 来获取。

oss 可以替代mongodb_UI_03


** javafx**

javaFX 是 JAVA 的 GUI 工具箱(GUI 是图形用户界面的缩写),用 JavaFX 创建桌面应用程序和游戏非

常容易。

javaFX 已经取代了 Swing 成为 Java 推荐的 GUI 工具包。此外,JavaFX在设计上比 Swing 更一致,并

且具有更多功能。它也更现代,使您能够使用布局文件(XML)设计 GUI 并使用 CSS 设置样式,就像

我们习惯于 Web 应用程序一样。 JavaFX 还将 2D 和 3D 图形、图表,以及音频、视频和嵌入式Web应

用程序集成到一个一致的GUI工具包中。

Gluon 公司已经将 JavaFX 移植到了 Android 和 iOS 上运行。

javafx 的核心构架:

oss 可以替代mongodb_xml_04


5.2 创建主程序

将项目自动生成的主程序替换成我们的 OSMonitorApplication。

```java
// 所有 javafx 主程序必须派生自 Application 类
// 子类必须 override 父类的 start 方法
public class OSMonitorApplication extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// 1. 加载 .fxml 文件
FXMLLoader loader = new
FXMLLoader(getClass().getClassLoader().getResource("os_monitor_tab1.fxml"));
Parent root = loader.load();
// 2. 创建一个场景对象
Scene scene = new Scene(root, 800, 600);
// 3. 给舞台对象设置标题
primaryStage.setTitle("OS Monitor");
// 4. 给舞台对象 stage 设置场景对象 scene
primaryStage.setScene(scene);
// 5. 展示舞台
primaryStage.show();
}
}

5.3 fxml 描述 UI
我们要用自己设计的 UI 替换工程自动生成的 .fxml 文件。
UI 的主题框架是通过 fxml 来描述。UI 交互比较简单,只有两个 tab 页。fxml 中所有元素名称都是
javafx 中的类名或者是类的属性名。元素的属性是 javafx 中类的属性。
OS Monitor UI 主框架包含两个 tab 也,用到的控件是 和 。 代表 tab
页所在的容器面板, 代表一个个的 tab 页。

<
?xml version="1.0" encoding="UTF-8"?>
// 导入类路径
<?import javafx.geometry.Insets?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" xmlns="http:///javafx/8.0.171"
xmlns:fx="http:///fxml/1"
fx:controller="com.haska.ui.OSMonitorController">
<children>
<TabPane tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab onSelectionChanged="#handleCPUSelectionChanged" text="CPU 占有
率">
<content>
...
</content>
</Tab>
<Tab text="磁盘空间统计">
<content>
...
</content>
</Tab>
</tabs>
</TabPane>
</children>
</VBox>

5.4 CPU 占有率 Tab 页设计
CPU 占有率 = CPU 执行程序时间 / 统计周期时间。比如,每 100ms 统计一次占用率,如果 CPU 执行
程序用了 90ms,那么 CPU 占用率是 90/100 = 90%。CPU 执行程序时间包括:用户程序执行时间 和
内核空间执行时间。
CPU 占有率 Tab 页主要是通过 控件绘制曲线图,x 轴 和 y 轴都用 控
件。通过 控件的 onSelectionChanged 属性设置监听事件的方法:
handleCPUSelectionChanged。

<LineChart fx:id="cpuChart" animated="false" HBox.hgrow="ALWAYS">
<xAxis>
<NumberAxis animated="false" label="Seconds" side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis animated="false" label="Percent" side="LEFT" />
</yAxis>
</LineChart>

5.5 磁盘扫描 Tab 页设计
磁盘扫描 Tab 页主要是用到了 控件,绘制一个树形表格。另外设计了一个
控件来选择文件目录,通 控件的 onAction 属性设置监听事件的方法:
handleSelectFile。

<Label text="选择文件目录:"></Label>
<Button mnemonicParsing="false" onAction="#handleSelectFile" prefWidth="80.0"
text="选择" GridPane.columnIndex="1">
<GridPane.margin>
<Insets bottom="5.0" top="5.0" />
</GridPane.margin>
</Button>
<TreeTableView fx:id="fileStat" HBox.hgrow="ALWAYS">
<columns>
<TreeTableColumn prefWidth="75.0" text="目录名">
<cellValueFactory>
<TreeItemPropertyValueFactory property="fileName" />
</cellValueFactory>
</TreeTableColumn>
<TreeTableColumn prefWidth="75.0" text="总长度">
<cellValueFactory>
<TreeItemPropertyValueFactory property="totalLength" />
</cellValueFactory>
</TreeTableColumn>
</columns>
</TreeTableView>

5.6 Controller 模块
Controller 主要是用于处理 UI 事件,需要将此类添加到 .fxml 文件中,我们用到的顶级容器是
,通过 fx:controller 属性设置 Controller 类的包路径,方法如下:

<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" xmlns="http:///javafx/8.0.171"
xmlns:fx="http:///fxml/1"
fx:controller="com.haska.ui.OSMonitorController">
</VBox>

在 Controller 中,我们需要处理两个事件:CPU 占有率和目录结构统计,代码如下:

// 磁盘目录扫描事件处理方法
public void handleSelectFile(ActionEvent actionEvent)
{
// 1. 打开文件选择对话框
// 2. 开启磁盘目录扫描线程
// 3. 渲染TreeTableView
} 
// CPU 占有率事件处理方法
public void handleCPUSelectionChanged(Event event) {
// 1. 创建一个定时器,每隔一秒获取一次 CPU 资源绘制曲线图
// 2. 绘制 LineChart
}

5.7 系统资源获取模块
系统资源获取采用的是 OperatingSystemMXBean,这是一个 JMX 接口,用于获取运行 JVM 的系统的
资源信息,比如,CPU 占有率,OS 版本,内存大小等等。我们用的是
com.sun.management.OperatingSystemMXBean 类,接口比较简单,参考官方文档即可。
绘制 CPU 占有率曲线的核心思想:

  1. 每隔一秒对 CPU 占有率进行一次采样,作为数轴的 y 坐标
  2. 我们一共保存 60 秒,即 1 分钟的样本点,时间作为 x 坐标。
  3. 用一个数组保存坐标 (x,y),每一次采样,需要把之前采样的坐标点的 x 坐标减 1,这样绘制的时候
    就会产生移动的效果。
    核心代码:
private static final int DATA_LENGH = 60;
private static XYPair[] cpuDatas = new XYPair[DATA_LENGH];
private static int firstIndex = DATA_LENGH;
private static void moveCPUData(double cpuPercetage){
int movIdx = -1;
if (firstIndex == 0){
movIdx = firstIndex + 1;
}else {
movIdx = firstIndex;
firstIndex--;
}
 for (; movIdx < cpuDatas.length; ++movIdx){
cpuDatas[movIdx-1].setX(cpuDatas[movIdx].getX()-1);
cpuDatas[movIdx-1].setY(cpuDatas[movIdx].getY());
} m
ovIdx--;
cpuDatas[movIdx] = new XYPair(movIdx, cpuPercetage);
}

5.8 文件目录扫描模块
文件目录扫描比较简单,核心思想是:用递归的方式遍历文件目录结构,统计某个目录下面所有子目录
占用总的磁盘空间大小,然后再做一个汇总。
代码片段:

File[] files = node.getFile().listFiles();
if (files == null) {
return;
}
 for (File file : files) {
FileTreeNode child = new FileTreeNode();
child.setFile(file);
child.setFileName(file.getName());
if (file.isDirectory()) {
scannerDirectory(child);
} else {
child.setTotalLength(file.length());
}
 node.setTotalLength(node.getTotalLength() + child.getTotalLength());
node.addChildNode(child);
}

6. 项目总结
项目优点:引入了 javafx 技术,通过图形化 界面展示 CPU 占有率和磁盘空间统计,显得更直观。
项目缺点:项目的所实现的功能相对简单,UI 不够美观。
项目扩展:我们还能将该项目写的更完善,可以往以下几个发展方向走:

  1. 增加关于内存使用情况的统计
  2. 增加关于网络上下行带宽的统计
  3. 可以美化一下 UI

7. 项目参考资料
http://tutorials.jenkov.com/javafx/index.html https://docs.oracle.com/javase/8/javase-clienttechnologies.htm
https://docs.oracle.com/javase/8/docs/api/java/lang/management/OperatingSystemMXBean.html