使用Java语言完成下列问题:“现有A、B两个线程,文件夹S中有10张图片,图片名分别为a1.jpg或a1.png、b2.jpg或b2.png、c3..d4..以此类推..k10.jpg或k10.png,A线程任务是往文件夹D中拷贝图片,B线程任务是每有一张图片拷贝进来,需将图片名称改成1.jpg或1.png。。以此类推到10.png或10.jpg,然后程序退出。要求:A线程不能一次拷贝多张图片,B线程不能一次修改多张图片名,即模拟生产者、消费者,拷贝进一个,修改一个名称,此题目需要用实验报告形式完成。” 分组(每组4-5人)进行探讨以下问题并形成报告提交: 1.如果不用多线程完成图片复制并改名,代码如何编写?(不可以在复制时就改名,需要先同文件名复制进来,再改名) 2.如果采用多线程,但是不加锁,即一个线程完成复制,另一个完成改名,代码如何编写/执行结果是什么样? 3.采用多线程加锁方式,代码如何编写
时间: 2023-12-01 09:02:42 浏览: 74
Java多线程自动播放图片的小程序
报告:
1. 如果不用多线程完成图片复制并改名,代码如下:
```java
import java.io.*;
public class CopyAndRename {
public static void main(String[] args) {
try {
// 创建文件夹
File dir = new File("D:/newFolder");
if (!dir.exists()) {
dir.mkdir();
}
// 复制和改名
int i = 1;
while (i <= 10) {
String srcFilePath = "S/" + getFileName(i);
String destFilePath = "D:/newFolder/" + i + getFileSuffix(i);
File srcFile = new File(srcFilePath);
File destFile = new File(destFilePath);
copyFile(srcFile, destFile);
renameFile(destFile, i);
i++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取文件名
public static String getFileName(int num) {
char c = (char) ('a' + num - 1);
return c + "" + num + ".jpg";
}
// 获取文件后缀
public static String getFileSuffix(int num) {
if (num % 2 == 0) {
return ".jpg";
}
return ".png";
}
// 复制文件
public static void copyFile(File srcFile, File destFile) throws IOException {
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
}
// 修改文件名
public static void renameFile(File file, int num) {
String newName = num + getFileSuffix(num);
File newFile = new File(file.getParent(), newName);
file.renameTo(newFile);
}
}
```
2. 如果采用多线程,但是不加锁,即一个线程完成复制,另一个完成改名,代码如下:
```java
import java.io.*;
public class CopyAndRename {
public static void main(String[] args) {
try {
// 创建文件夹
File dir = new File("D:/newFolder");
if (!dir.exists()) {
dir.mkdir();
}
// 创建A线程
Thread threadA = new Thread(() -> {
int i = 1;
while (i <= 10) {
String srcFilePath = "S/" + getFileName(i);
String destFilePath = "D:/newFolder/" + i + getFileSuffix(i);
File srcFile = new File(srcFilePath);
File destFile = new File(destFilePath);
try {
copyFile(srcFile, destFile);
} catch (IOException e) {
e.printStackTrace();
}
i++;
}
});
// 创建B线程
Thread threadB = new Thread(() -> {
int i = 1;
while (i <= 10) {
String filePath = "D:/newFolder/" + i + getFileSuffix(i);
File file = new File(filePath);
renameFile(file, i);
i++;
}
});
// 启动线程
threadA.start();
threadB.start();
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取文件名
public static String getFileName(int num) {
char c = (char) ('a' + num - 1);
return c + "" + num + ".jpg";
}
// 获取文件后缀
public static String getFileSuffix(int num) {
if (num % 2 == 0) {
return ".jpg";
}
return ".png";
}
// 复制文件
public static void copyFile(File srcFile, File destFile) throws IOException {
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
}
// 修改文件名
public static void renameFile(File file, int num) {
String newName = num + getFileSuffix(num);
File newFile = new File(file.getParent(), newName);
file.renameTo(newFile);
}
}
```
执行结果是有可能出现A线程复制文件还未完成,B线程就开始修改文件名的情况,导致修改失败。
3. 采用多线程加锁方式,代码如下:
```java
import java.io.*;
public class CopyAndRename {
public static void main(String[] args) {
try {
// 创建文件夹
File dir = new File("D:/newFolder");
if (!dir.exists()) {
dir.mkdir();
}
// 创建锁
Object lock = new Object();
// 创建A线程
Thread threadA = new Thread(() -> {
int i = 1;
while (i <= 10) {
String srcFilePath = "S/" + getFileName(i);
String destFilePath = "D:/newFolder/" + i + getFileSuffix(i);
File srcFile = new File(srcFilePath);
File destFile = new File(destFilePath);
try {
copyFile(srcFile, destFile);
} catch (IOException e) {
e.printStackTrace();
}
// 加锁
synchronized (lock) {
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
}
});
// 创建B线程
Thread threadB = new Thread(() -> {
int i = 1;
while (i <= 10) {
String filePath = "D:/newFolder/" + i + getFileSuffix(i);
File file = new File(filePath);
// 加锁
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
renameFile(file, i);
lock.notify();
}
i++;
}
});
// 启动线程
threadA.start();
threadB.start();
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取文件名
public static String getFileName(int num) {
char c = (char) ('a' + num - 1);
return c + "" + num + ".jpg";
}
// 获取文件后缀
public static String getFileSuffix(int num) {
if (num % 2 == 0) {
return ".jpg";
}
return ".png";
}
// 复制文件
public static void copyFile(File srcFile, File destFile) throws IOException {
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
}
// 修改文件名
public static void renameFile(File file, int num) {
String newName = num + getFileSuffix(num);
File newFile = new File(file.getParent(), newName);
file.renameTo(newFile);
}
}
```
加锁方式可以保证A线程完成复制后,B线程才能进行修改文件名,避免了修改失败的情况。
阅读全文