java多线程基础——实现对目录的监控

多线程基础概述

1.进程与线程
进程:操作系统中正在执行的一个任务(程序),比如:QQ,微信,idea,qq音乐都称之为进程。
线程:线程是进程中的一条执行路径,比如电脑管家,在病毒查杀的同时,清理垃圾,电脑加速等操作。

2. 线程的调度(CPU)
(1)平均分配执行时间(正常)
(2)抢占式运行(设置优先级)

3. 线程的状态
(1). 新建状态(线程刚创建)
(2). 就绪状态(线程启动)
(3). 运行状态(线程得到CPU的时间片)
(4). 阻塞状态(线程还未执行完,但是CPU已经将时间片分配其他线程)
(5). 死亡状态(线程执行完毕或者正常中断)
java的多线程机制中将线程分为6种状态
将阻塞分为:限时阻塞(在一个时间段之内阻塞,过了这个时间,重新进度调度队列)以及无限阻塞(必须的到通知的情况下才能继续进度调度队列)。

4. 线程创建方式
(1).继承Thread类(重写run());
(2).实现Runnable接口(重写run()),;
(3).实现Callable接口,通过FutureTask调度(JDK5新增并发编程)(重写call());
(4).使用线程池框架Executor创建(JDK5新增并发编程)

5.三种创建方式的区别
(1). 使用Thread的方式为继承,一旦继承Thread就无法再继承其他类,扩展性存在一定影响 ;可以直接创建对象并调用start启动
(2). 实现Runnable接口,类还可以再继承其他类或者实现其他接口,扩展性方面不受影响,run方法不能抛出异常;启动线程时还是需要由Thread类启动
(3). 实现Callable接口,实现的方法call有返回值,还提供了泛型支持,并且call方法允许抛出异常,一般用于并行计算,Callable接口需要有FutureTask包装并且被Thread启动。

6.线程启动
在这里插入图片描述7.守护线程
守护线程也称之为后台线程,即为其他线程提供服务的线程;守护线程会随着主线程的结束而结束;如果需要设置一条线程为守护线程,则只需要调用setDaemon(true)。

8.线程中断
推荐的线程中断方法:标记中断
(1).在线程类中声明一个全局变量作为标记(整数,布尔等);
(2).当标记为运行状态时线程正常执行;
(3).一旦将当前线程的标记状态修改为终止则不再执行线程。

利用线程实现对目录的监控

一个线程监控一个文件的修改,一个线程监控一个目录中(一级目录)是否有新文件产生,若有新文件产生或者删除文件,则显示新增文件或者删除文件的名称和修改时间。(两者间无关)

运行效果:
在这里插入图片描述

监控文件

import java.io.File;
import java.time.LocalDateTime;

/**
 * 监控文件是否改变
 * @author bxwl
 * @create 2020-07-17 13:43
 */
public class FileListener extends Thread{

    private File target;
    /**记录文件的最后修改时间*/
    private long lastModify;

    public FileListener(File target){
        this.target = target;
    }

    @Override
    public void run() {
        //记录文件的最后修改时间
        lastModify = target.lastModified();
        System.out.println("开始监控:"+ LocalDateTime.now());
        while(true){
            //不断获取最后修改时间
            long newTime = target.lastModified();
            //若最后修改时间不等,则文件被修改
            if(newTime != lastModify){
                System.out.println(target.getName()+"被修改,修改时间:"+Tools.getFmtTime(newTime));
                //更新最后修改时间
                lastModify = newTime;
            }
            try {
                sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

监控一个一级目录

import java.io.File;
import java.time.LocalDateTime;

/**
 * 监控一个目录中(一级目录)是否有新文件产生
 * @author bxwl
 * @create 2020-07-17 13:44
 */
public class DirListener extends Thread{

    /**监控的目录*/
    private File dir;
    /**存储原目录的文件的数组*/
    private File[] files;

    public DirListener(File dir){
        this.dir = dir;
    }

    @Override
    public void run() {
        //获取所有子文件对象
        files = dir.listFiles();
        File[] newFiles;
        System.out.println("开始监控目录:"+ LocalDateTime.now());
        while(true){
            newFiles = dir.listFiles();
            /*
            判断是否有新增文件
            得到的文件数组长度大于之前的数组长度,则新增了文件
             */
            if(newFiles.length > files.length){
                for(File f:newFiles){
                    //标记当前文件是新文件
                    boolean flag = true;
                    //遍历原来的数组,在其中查找是否存在新文件数组的文件
                    for(File f2:files){
                        //判断新数组中的文件是否跟原数组中的文件匹配
                        if(f.getName().equals(f2.getName())){
                            //匹配则表示不是新文件
                            flag = false;
                        }
                    }
                    //判断标记是否依然是true(是新文件)
                    if(flag){
                        System.out.println("新增的文件:"+f.getName()+"新增时间:"+Tools.getFmtTime(f.lastModified()));
                    }
                }
                //更新缓存
                files = newFiles;
            }else if(newFiles.length < files.length){
                /*
                 文件数组长度小于原文件数组长度,则表示删除了文件
                 */
                for(File f:files){
                    //标记当前文件是新文件
                    boolean flag = true;
                    for(File f2:newFiles){
                        //判断新数组中的元素是否跟原数组中的元素匹配
                        if(f.getName().equals(f2.getName())){
                            flag = false;
                        }
                    }
                    //判断标记是否依然是true(是新文件)
                    if(flag){
                        System.out.println("删除的文件:"+f.getName()+"删除时间:"+Tools.getFmtTime(f.lastModified()));
                    }
                }
                //更新缓存
                files = newFiles;
            }
            try {
                //没5s监听一次
                sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

处理时间的工具类

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 工具类
 * @author bxwl
 * @create 2020-07-17 13:59
 */
public class Tools {

    /**
     * 对提供的毫秒数表示的时间格式化为特定的字符串
     * @param time
     * @return
     */
    public static String getFmtTime(long time){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date d = new Date(time);
        return sdf.format(d);
    }
}

主方法

import java.io.File;

/**
 * @author bxwl
 * @create 2020-07-17 13:46
 */
public class EnterMain {

    public static void main(String[] args) {

        File target = new File("D:\\新建文件夹\\java\\java学习\\test\\b.txt");
        File dir = new File("D:\\新建文件夹\\java\\java学习\\test");
        //创建并启动文件监控线程
        FileListener fl = new FileListener(target);
        fl.start();
        //创建并启动目录监控线程
        DirListener dl = new DirListener(dir);
        dl.start();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值