单例模式:只能有一个实例
检测到有U盘插入时,查找设备中的所有文件
在U盘插入之前先获取系统开始的盘符数。两个线程分别为生产者和消费者
生产者:循环检测系统盘符,若判断出盘符数增多,则该线程等待并唤醒消费者。
消费者:一直处于等待状态,直到被生产者唤醒。
单例:
public class UDiskMonitor {
//设为私有
private static final Logger logger = LoggerFactory.getLogger(UDiskMonitor.class);
private static UDiskMonitor sUsbDiskMonitor;
private UDiskMonitor() {
File[] dir = File.listRoots();//File类方法:获取盘符
count = dir.length;
ResourceFileRunnable rf = new ResourceFileRunnable(count);
Thread t1 = new Thread(new ProducerUsbDisk(rf));//生产者
Thread t2 = new Thread(new ConsumerUsbDisk(rf));//消费者
t1.start();
t2.start();
}
//获取或者创建实例
public static UDiskMonitor getInstance() {
if(sUsbDiskMonitor == null) {
sUsbDiskMonitor = new UsbDiskMonitor();
}
return sUsbDiskMonitor;
}
public static int count = 0;
public static void main(String[] args) throws Exception {
UDiskMonitor.getInstance();
}
}
生产者
因为不需要返回值,所以采用实现Runnable接口的run()方法
class ProducerUsbDisk implements Runnable {
private ResourceFileRunnable rf = null;
public ProducerUsbDisk(ResourceFileRunnable rf) {
this.rf = rf;
}
@Override
public void run() {
while (true) {
rf.searchFile();//获取盘符
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者
class ConsumerUsbDisk implements Runnable {
private ResourceFileRunnable rf = null;
public ConsumerUsbDisk(ResourceFileRunnable rf) {
this.rf = rf;
}
@Override
public void run() {
while (true) {
rf.consumeFile();//消费
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ResourceFileRunnable 类
class ResourceFileRunnable {
private static final Logger logger = LoggerFactory.getLogger(ResourceFileRunnable.class);
private static final String MEDIA_PATH = "media/";
private static final String PLAN_JSON_NAME = "planplaylist.json";
private int count = 0; //判断是否有设备插入的标记
private boolean flag = false;
private File[] dirs;
public ResourceFileRunnable(int count) {
this.count = count;
}
//获取所有文件名
public static void getAllFiles(File dir) throws Exception {
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory() && "rt".equalsIgnoreCase(f.getName())) {
File[] rtFiles = f.listFiles();
for(File rtF : rtFiles) {
if("playlist.json".equalsIgnoreCase(rtF.getName())) {
cpFile(rtF.getAbsolutePath(),PLAN_JSON_NAME);
}
if(rtF.isDirectory()) {
File[] subFiles = rtF.listFiles();
for(File subF : subFiles) {
if(subF.isDirectory()) {
File[] sub2Files = subF.listFiles();
for(File sub2F : sub2Files) {
cpFile(subF.getAbsolutePath(), MEDIA_PATH + rtF.getName()
+ "/" + subF.getName() + "/" + sub2F.getName());
}
} else {
cpFile(subF.getAbsolutePath(), MEDIA_PATH + rtF.getName() + "/" + subF.getName());
}
}
} else {
cpFile(rtF.getAbsolutePath(),MEDIA_PATH + rtF.getName());
}
}
String planStr = FileUtils.readFile(PLAN_JSON_NAME);
RtPlan plan = JSON.parseObject(planStr, RtPlan.class);
NettyClient.getInstance().planReceived(plan);
}
}
}
}
//查找资源--生产者使用
public synchronized void searchFile() {
if (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
dirs = File.listRoots();
if (dirs.length != count) {
flag = true;
notify();//唤醒消费者
}
}
//消费资源--消费者使用
public synchronized void consumeFile() {
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (dirs.length > count) {
try {
getAllFiles(dirs[dirs.length - 1]);
} catch (Exception e) {
e.printStackTrace();
}
}
count = dirs.length;
flag = false;
notify();
}
private static void cpFile(String srcPath, String targetPath) {
long start = System.currentTimeMillis();
try {
//源文件
File src = new File(srcPath);
//目标文件
File desc = new File(targetPath);
File descDir = desc.getParentFile();
if(descDir != null && !descDir.exists()) {
descDir.mkdirs();
}
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(desc);
byte[] b = new byte[1024 * 1024];
int len = -1;
while ((len = fis.read(b)) != -1) {
fos.write(b, 0, len);
fos.flush();
}
fos.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
}
}