我被分配了將給定檔案的所有有序內容寫入 result.txt 的任務。首先,檔案名被拆分為不同的 Arraylist,其中每個檔案都包含一個格式為 #n/N 的標簽,其中 N 是檔案總數。例如
英國探險家詹姆斯克拉克羅斯率領第一次探險到達北極#001/004
來自檔案 1831-06-01.txt
我的代碼的問題在于它分別按 1、4、2、3 的順序撰寫。但是,結果必須按 1、2、3、4 的順序排列。這可能是由于缺乏同步。盡管如此,我仍在努力解決這個問題。
這是我的代碼:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
class PopThread implements Runnable {
ArrayList<String> fileList;
public PopThread(ArrayList<String> fileList) {
this.fileList = fileList;
}
@Override
public void run() {
//System.out.println("running\n");
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
long startTime = System.nanoTime();
System.out.println("fileList: " fileList);
ArrayList<String> sortedFileList = sortFiles(fileList);
File resultFile = new File("result.txt");
for (String filename : sortedFileList) {
Writer w1 = new Writer(filename, resultFile);
Thread t = new Thread(w1);
t.setPriority(Thread.MAX_PRIORITY);
t.start();
}
long stopTime = System.nanoTime();
//System.out.println("Total execution time: " (stopTime - startTime));
}
public ArrayList<String> readFiles(String filename) {
ArrayList<String> list = new ArrayList<String>();
try {
File myObj = new File(filename);
Scanner s = new Scanner(myObj);
while (s.hasNext()) {
list.add(s.next());
}
s.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return list;
}
public int getNumber(String filename) {
String lastLine = "";
String sCurrentLine;
int identifier_integer = -1;
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
while ((sCurrentLine = br.readLine()) != null) {
lastLine = sCurrentLine;
}
String identifier_number = lastLine.substring(1,4);
identifier_integer = Integer.parseInt(identifier_number);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return identifier_integer;
}
public ArrayList<String> sortFiles(ArrayList<String> listFileName) {
int i = listFileName.size();
boolean sorted = false;
while ( (i > 1) && (!(sorted)) ) {
sorted = true;
for (int j = 1; j < i; j ) {
if ( getNumber(listFileName.get(j-1)) > getNumber(listFileName.get(j)) ) {
String temp = listFileName.get(j-1);
listFileName.set(j-1, listFileName.get(j));
listFileName.set(j, temp);
sorted = false;
}
}
i--;
}
return listFileName;
}
}
class Writer implements Runnable {
String filename;
File resultFile;
public Writer(String filename, File resultFile) {
this.filename = filename;
this.resultFile = resultFile;
}
@Override
public void run() {
String content;
content = readFromFile(filename);
writeToFile(resultFile, content);
}
private static void writeToFile(File resultFile, String content) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile, true));
writer.write(content);
//writer.write("file content written");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
static String readFromFile(String filename) {
StringBuffer content = new StringBuffer();
try {
String text;
BufferedReader reader = new BufferedReader(new FileReader(filename));
while ((text = reader.readLine()) != null) {
content.append(text);
content.append("\n");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return content.toString();
}
}
public class q4 {
public static void main(String[] args) {
ArrayList<String> filesOne = new ArrayList<String>();
filesOne.add("1831-06-01.txt");
filesOne.add("2003-08-27.txt");
ArrayList<String> filesTwo = new ArrayList<String>();
filesTwo.add("1961-04-12.txt");
filesTwo.add("1972-12-11.txt");
PopThread popRunnableOne = new PopThread(filesOne);
PopThread popRunnableTwo = new PopThread(filesTwo);
Thread threadOne = new Thread(popRunnableOne);
Thread threadTwo = new Thread(popRunnableTwo);
threadOne.start();
threadTwo.start();
try {
threadOne.join();
threadTwo.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
(注意:類 q4 不能更改)
uj5u.com熱心網友回復:
這個任務太可怕了。你有我的同情。
您的兩個執行緒必須相互通信。每個執行緒都必須知道,另一個執行緒接下來要輸出的檔案名是什么。而且,他們將不得不輪流進行。每個執行緒都需要回圈:
當我下一個檔案的日期小于或等于另一個執行緒下一個檔案的日期時,輸出我的下一個檔案,
告訴另一個執行緒,“輪到你了,”
如果我沒有更多檔案,則退出(從
run()方法回傳),否則,等待另一個執行緒告訴我又輪到我了,回到步驟 1。
不得不輪流是任務中最糟糕的部分。任何時候你發現自己需要讓執行緒輪流做某事——任何時候你需要讓執行緒以特定的順序做某事——這清楚地表明所有的事情都應該由一個執行緒來完成。
執行緒可以通信的唯一方式是通過共享變數。您的老師告訴您不要修改課程,這對您造成了極大q4的傷害。這會阻止您PopThread通過其建構式將任何共享物件傳遞給您的實作。
您的兩個執行緒可以共享任何變數的唯一另一種方法是制作 variables static。強迫你使用static是任務中第二糟糕的部分。如果你繼續學習軟體工程,你會發現這static是一種反模式。使用static變數的程式很脆弱(即難以修改),并且它們難以測驗。
強迫你使用靜態變數也會讓你的執行緒做額外的作業來弄清楚誰是誰。通常,我會做這樣的事情,這樣每個執行緒都會自動知道哪個狀態是它自己的,哪個屬于另一個人:
class SharedState { ... }
class PopThread {
public PopThread(
SharedState myState,
SharedState otherThreadState,
ArrayList<String> fileList
) {
this.myState = myState;
this.otherGuyState = otherThreadState;
this.fileList = fileList;
...initialize this.myState...
}
...
}
class q4 {
public static void main(String[] args) {
SharedState stateOne = new SharedState();
SharedState stateTwo = new SharedState();
PopThread popRunnableOne = new PopThread(stateOne, stateTwo, filesOne);
PopThread popRunnableTwo = new PopThread(stateTwo, stateOne, filesTwo);
...
}
}
The best way I can think of with static variables would be to have an array of two SharedState, and have the threads use an AtomicInteger to each assign themself one of the two array slots:
class PopThread {
static SharedState[] state = new SharedState [2];
static AtomicInteger nextStateIndex = new AtomicInteger(0);
public PopThread(
SharedState myState,
SharedState otherThreadState,
ArrayList<String> fileList
) {
myStateIndex = nextStateIndex.getAndIncrement();
otherGuysStateIndex = myStateIndex ^ 1;
this.fileList = fileList;
...initialize state[myStateIndex]...
}
...
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/457401.html
