java多線程讀取文件
A. java多線程讀寫文件
public static void main(String[] args) {
File data = new File("data.txt");
try {
InputStreamReader read = new InputStreamReader(new FileInputStream(
data), "UTF-8");
final BufferedReader bufferedReader = new BufferedReader(read);
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
String lineTXT = null;
synchronized (bufferedReader) {
try {
while ((lineTXT = bufferedReader.readLine()) != null) {
System.out.println(Thread.currentThread()+":"+lineTXT);
bufferedReader.notify();
bufferedReader.wait();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
bufferedReader.notifyAll();
}
}
}
}).start();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
B. java多線程同時讀取一個文件,這個方法可行嗎
不可行。每次讀取文件都需要創建緩存文件流,很占內存,而且多次讀取實際上也是一個文件,還不如直接讀取文件,之後通過條件多次獲取需要的內容來的實際。
可以通過BufferedReader 流的形式進行流緩存,之後通過readLine方法獲取到緩存的內容。
BufferedReader bre = null;
try {
String file = "D:/test/test.txt";
bre = new BufferedReader(new FileReader(file));//此時獲取到的bre就是整個文件的緩存流
while ((str = bre.readLine())!= null) // 判斷最後一行不存在,為空結束循環
{
System.out.println(str);//原樣輸出讀到的內容,此處可以添加條件進行不同的處理
};
備註: 流用完之後必須close掉,如上面的就應該是:bre.close(),否則bre流會一直存在,直到程序運行結束。
C. 使用Java多線程實現任務分發
多線程下載由來已久 如 FlashGet NetAnts 等工具 它們都是依懶於 HTTP 協議的支持(Range 欄位指定請求內容範圍) 首先能讀取出請求內容 (即欲下載的文件) 的大小 劃分出若干區塊 把區塊分段分發給每個線程去下載 線程從本段起始處下載數據及至段尾 多個線程下載的內容最終會寫入到同一個文件中
只研究有用的 工作中的需求 要把多個任務納凱分派給Java的多個線程去執行 這其中就會有一個任務列表指派到線程的策略思考 已知 一個待執行的任務列表 指定要啟動的線程數 問題是 每個線程實際要執行哪些任務
使用Java多線程實現這種任務分發的策略是 任務列表連續按線程數分段 先保證每線程平均能分配到的任務數 餘下的任務從前至後依次附加到線程中——只是數量上 實際每個線程執行的任務都還是連續的 如果出現那種僧多(線程) 粥(任務) 少的情況 實際啟動的線程數就等於任務數 一挑一 這里只實現了每個線程各掃自謹宴家門前雪 動作快的完成後眼見別的線程再累都是愛莫能助
實現及演示代碼如下 由三個類實現 寫在了一個 Java 文件中 TaskDistributor 為任務分發器 Task 為待執行的任務 WorkThread 為自定的工作洞晌喚線程 代碼中運用了命令模式 如若能配以監聽器 用上觀察者模式來控制 UI 顯示就更絕妙不過了 就能實現像下載中的區塊著色跳躍的動感了 在此定義下一步的著眼點了
代碼中有較為詳細的注釋 看這些注釋和執行結果就很容易理解的 main() 是測試方法
package mon;import java util ArrayList;import java util List;/*** 指派任務列表給線程的分發器* @author Unmi* QQ: Email: * MSN: */public class TaskDistributor {/*** 測試方法* @param args*/public static void main(String[] args) {//初始化要執行的任務列表List taskList = new ArrayList();for (int i = ; i < ; i++) {taskList add(new Task(i));}//設定要啟動的工作線程數為 個int threadCount = ;List[] taskListPerThread = distributeTasks(taskList threadCount);System out println( 實際要啟動的工作線程數 +taskListPerThread length);for (int i = ; i < taskListPerThread length; i++) {Thread workThread = new WorkThread(taskListPerThread[i] i);workThread start();}}/*** 把 List 中的任務分配給每個線程 先平均分配 剩於的依次附加給前面的線程* 返回的數組有多少個元素 (List) 就表明將啟動多少個工作線程* @param taskList 待分派的任務列表* @param threadCount 線程數* @return 列表的數組 每個元素中存有該線程要執行的任務列表*/public static List[] distributeTasks(List taskList int threadCount) {// 每個線程至少要執行的任務數 假如不為零則表示每個線程都會分配到任務int minTaskCount = taskList size() / threadCount;// 平均分配後還剩下的任務數 不為零則還有任務依個附加到前面的線程中int remainTaskCount = taskList size() % threadCount;// 實際要啟動的線程數 如果工作線程比任務還多// 自然只需要啟動與任務相同個數的工作線程 一對一的執行// 畢竟不打算實現了線程池 所以用不著預先初始化好休眠的線程int actualThreadCount = minTaskCount > ? threadCount : remainTaskCount;// 要啟動的線程數組 以及每個線程要執行的任務列表List[] taskListPerThread = new List[actualThreadCount];int taskIndex = ;//平均分配後多餘任務 每附加給一個線程後的剩餘數 重新聲明與 remainTaskCount//相同的變數 不然會在執行中改變 remainTaskCount 原有值 產生麻煩int remainIndces = remainTaskCount;for (int i = ; i < taskListPerThread length; i++) {taskListPerThread[i] = new ArrayList();// 如果大於零 線程要分配到基本的任務if (minTaskCount > ) {for (int j = taskIndex; j < minTaskCount + taskIndex; j++) {taskListPerThread[i] add(taskList get(j));}taskIndex += minTaskCount;}// 假如還有剩下的 則補一個到這個線程中if (remainIndces > ) {taskListPerThread[i] add(taskList get(taskIndex++));remainIndces ;}}// 列印任務的分配情況for (int i = ; i < taskListPerThread length; i++) {System out println( 線程 + i + 的任務數 +
taskListPerThread[i] size() + 區間[ + taskListPerThread[i] get( ) getTaskId() + + taskListPerThread[i] get(taskListPerThread[i] size() ) getTaskId() + ] );}return taskListPerThread;}}/*** 要執行的任務 可在執行時改變它的某個狀態或調用它的某個操作* 例如任務有三個狀態 就緒 運行 完成 默認為就緒態* 要進一步完善 可為 Task 加上狀態變遷的監聽器 因之決定UI的顯示*/class Task {public static final int READY = ;public static final int RUNNING = ;public static final int FINISHED = ;private int status;//聲明一個任務的自有業務含義的變數 用於標識任務private int taskId;//任務的初始化方法public Task(int taskId){this status = READY;this taskId = taskId;}/*** 執行任務*/public void execute() {// 設置狀態為運行中setStatus(Task RUNNING);System out println( 當前線程 ID 是 + Thread currentThread() getName()+ | 任務 ID 是 +this taskId);// 附加一個延時try {Thread sleep( );} catch (InterruptedException e) {e printStackTrace();}// 執行完成 改狀態為完成setStatus(FINISHED);}public void setStatus(int status) {this status = status;}public int getTaskId() {return taskId;}}/*** 自定義的工作線程 持有分派給它執行的任務列表*/class WorkThread extends Thread {//本線程待執行的任務列表 你也可以指為任務索引的起始值private List taskList = null;private int threadId;/*** 構造工作線程 為其指派任務列表 及命名線程 ID* @param taskList 欲執行的任務列表* @param threadId 線程 ID*/public WorkThread(List taskList int threadId) {this taskList = taskList;this threadId = threadId;}/*** 執行被指派的所有任務*/public void run() {for (Task task : taskList) {task execute();}}}
執行結果如下 注意觀察每個Java多線程分配到的任務數量及區間 直到所有的線程完成了所分配到的任務後程序結束
線程 的任務數 區間[ ]線程 的任務數 區間[ ]線程 的任務數 區間[ ]線程 的任務數 區間[ ]線程 的任務數 區間[ ]實際要啟動的工作線程數 當前線程 ID 是 Thread | 任務 ID 是 當前線程 ID 是 Thread | 任務 ID 是 當前線程 ID 是 Thread | 任務 ID 是 當前線程 ID 是 Thread | 任務 ID 是 當前線程 ID 是 Thread | 任務 ID 是 當前線程 ID 是 Thread | 任務 ID 是 當前線程 ID 是 Thread | 任務 ID 是 當前線程 ID 是 Thread | 任務 ID 是
上面坦白來只算是基本功夫 貼出來還真見笑了 還有更為復雜的功能
lishixin/Article/program/Java/gj/201311/27443
D. java中怎麼用多個線程同時對一個文件讀取,最終將文件內容保存到一個位元組數組中去呢
多線程讀取文件在一塊硬碟上沒用,瓶頸在硬碟I/O,而不在CPU和內存。讀取文件時,CPU不用復雜的計算工作,只是數據傳輸而已,多線程反而造成磁頭來回移動,效率不高。如果是兩塊以上的硬碟,可以用不同的線程訪問不同的硬碟,效率比單線程要高
而且多線程操作同一文件除了效率還會有多線程問題,多個線程同時往數組里存數據還會有線程安全問題,如果不同步處理讀取的文件就是錯誤的。
如果讀取的話只能設置每個線程各自讀取偏 移量
讀取文件大小(比如大小是200K)。 2,啟動5個線程,第一個線程讀到40,第二個線程跳過40在讀到80,總之得合理安排好各個線程讀取的大小。這樣才能不重復讀取。大數據處理框架maprece原理和此類似