多线程-生产者消费者模式实战
程序员文章站
2022-05-06 10:08:27
...
多线程-生产者消费者模式实战
1 ) 介绍
该实战实现的主要功能是扫描电脑中的一个磁盘中的指定后缀名的文件,将匹配出来的文件都复制到指定的目录下,
现在我们代码中实现的是将磁盘中的所有jpg格式的图片都转移到我指定的文件夹中。
该代码的大体思路是:生产者的职责是负责在磁盘中寻找符合的文件名称,将文件名称放入队列当中,寻找文件的时候需要递归,消费者的职责是从队列中取出文件的地址,进行复制
2)生产者代码
生产者执行时无论队列中是否有资源都应该生产,但是如果生产者执行的时候,消费者之前就执行到了,所有消费者会进行一个等待,这个时候需要生产者进行一个唤醒
import java.io.File;
import java.util.Arrays;
import java.util.Queue;
/**
* @author 寒夜清风
* @version 1.0
* @Desc 不积跬步无以至千里
* @date 2020/7/2 14:13
* 生产者
*/
public class Find extends Thread {
private resource resource;
private String path;
private String[] names;
private String to;
Find(resource resource, String path, String[] names, String to) {
this.resource = resource;
this.path = path;
this.names = names;
this.to = to;
}
@Override
public void run() {
find(path, names);
//生产者完成工作设立一个标制,告诉消费者生产者完成工作了
resource.setEnd();
System.out.println("设置了出口");
}
public void find(String path, String[] names) {
File fileAll = new File(path);
String[] list = fileAll.list();
for (String s : list) {
//如果包含就打印出来
for (String name : names) {
if (s.contains(name)) {
synchronized (resource.lock) {
//如果为true 代表队列为空
int a = 0;
if (resource.isFlag()) {
a = 1;
}
//生产者先生产
Node node = new Node();
node.setFromName(path + "\\" + s);
node.setToName(s);
resource.addQueue(node);
//生产完
if (a == 1) {
resource.lock.notifyAll();
}
}
}
}
}
File[] files = fileAll.listFiles();
for (File file : files) {
// 如果是文件夹的话
if (isfolder(file)) {
find(path + "\\" + file.getName(), names);
}
}
}
public boolean isfolder(File file) {
if (file.isDirectory() && !"DeliveryOptimization".equals(file.getName()) && !file.isHidden() && !"WindowsApps".equals(file.getName())) {
return true;
}
return false;
}
}
2)消费者代码
消费者先执行的时候需要一个等待,当生产者完工标为true的时候,就跳出循环,消费者也完工
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author 寒夜清风
* @version 1.0
* @Desc 不积跬步无以至千里
* @date 2020/7/2 17:38
* 消费者
*/
public class CopyFile extends Thread {
private resource resource;
private String desPathStr;
CopyFile(resource resource, String desPathStr) {
this.resource = resource;
this.desPathStr = desPathStr;
}
@Override
public void run() {
try {
copy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void copy() throws InterruptedException {
while (1 == 1) {
synchronized (resource.lock) {
// 如果生产者宣布结束了,那就结束了
if (resource.end) {
break;
}
//如果为true 代表队列为空
if (resource.isFlag()) {
//如果没有资源 等待
resource.lock.wait(1000);
} else {
Node node = resource.getQueue();
String newFileName = node.getFromName().substring(node.getFromName().lastIndexOf("\\") + 1);
//源文件地址
desPathStr = desPathStr + File.separator;
try {
//创建输入流对象
FileInputStream fis = new FileInputStream(node.getFromName());
//创建输出流对象
FileOutputStream fos = new FileOutputStream(desPathStr + "\\" + node.getToName());
//创建搬运工具
byte datas[] = new byte[1024 * 8];
//创建长度
int len = 0;
//循环读取数据
while ((len = fis.read(datas)) != -1) {
fos.write(datas, 0, len);
}
fis.close();//释放资源
fis.close();//释放资源
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
4)执行代码
/**
* @author 寒夜清风
* @version 1.0
* @Desc 不积跬步无以至千里
* @date 2020/7/2 18:05
*/
public class Main {
public static void main(String[] args) throws InterruptedException {
long l = System.currentTimeMillis();
// 扫描的盘
String path = "d:\\";
// 要扫描出来的后缀名
String str[] = {".jpg"};
// 将资源找出放在 这个目录下
String to = "G:\\所有的图片2";
resource resource = new resource();
//生产者
Find find = new Find(resource, path, str, to);
//消费者
CopyFile copyFile = new CopyFile(resource, to);
find.start();
find.join();
long l1 = System.currentTimeMillis();
System.out.println(l1 - l);
}
}
5)效果
这样所有的图片就过来了,okok
`
下一篇: 面试算法题(1)--链表反转