一.現網問題描述
現網在同一文件分片上傳的過程中發生創建目錄失敗,拋出異常
二,定位問題
從日誌中能夠看出上傳分片的順序是1,2,0,3,4
第二個分片請求上傳首先到達進行創建目錄
第三個分片請求上傳進行創建目錄失敗
看代碼進行分析
已經很明顯啦,
導致的問題是分片上傳的過程中併發上傳分片,同時創建相同目錄,導致在下面代碼紅色標記的地方發生併發。
而file.mkdirs方法如果目錄已經存在,則返回false;如果目錄不存在,創建成功,返回false
三.修改驗證
修改代碼爲
併發驗證
package testJVm;
import java.io.File;
import java.util.concurrent.CountDownLatch;
public class TestDir
{
public static void main(String[] args)
throws InterruptedException
{
CountDownLatch countDown = new CountDownLatch(1);
CountDownLatch await = new CountDownLatch(50); // 依次創建並啓動處於等待狀態的5個MyRunnable線程
for (int i = 0; i < 50; ++i)
{
new Thread(new MyRunnable(countDown, await)).start();
}
System.out.println("用於觸發處於等待狀態的線程開始工作......");
System.out.println("用於觸發處於等待狀態的線程工作完成,等待狀態線程開始工作......");
countDown.countDown();
await.await();
System.out.println("Bingo!");
}
public static String creatDIRS(String path)
{
File file = new File(path);
if (file.exists())
{
System.out.println("file is exist, path = " + path);
return path;
}
if (!file.mkdirs())
{
System.out.println("file mkdirs is fail, path = " + path);
if (!file.exists())
{
System.out.println("file make director error");
}
else
{
System.out.println("OK");
}
}
return path;
}
}
package testJVm;
import java.util.concurrent.CountDownLatch;
public class MyRunnable implements Runnable
{
private final CountDownLatch countDown;
private final CountDownLatch await;
private final String path ="c://opt//hua//wei";
public MyRunnable(CountDownLatch countDown, CountDownLatch await)
{
this.countDown = countDown;
this.await = await;
}
public void run()
{
try
{
countDown.await();// 等待主線程執行完畢,獲得開始執行信號...
System.out.println("處於等待的線程開始自己預期工作......");
TestDir.creatDIRS(path);
await.countDown();// 完成預期工作,發出完成信號...
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
經過驗證,併發創建文件時,不會出現拋異常的場景