特长:大中小型javaweb后端架构、功能代码编写,java桌面端程序开发、java群发(文章/邮件/投票等)系统架构和编写,javaweb、java桌面端全栈、爬虫系统开发。工作编写过写安卓、ios、微信小程序,c程序、php程序、python程序。
【Other Blog:
my.csdn.net/ouchuquan 和
blog.sina.com.cn/u/2430843520】
在写之前先声明,本文是基于之前在博客园网站上检索到的一份JAVA多线程读写文件的示例,我在写自己的程序时是在那位作者写的基础上做了改良,但已不记得原文的地址。如果有知情者,烦请帖出地址,我在此文上加入引用或转载。
本程序是基于这么一种考虑,某系统后台有个将近2G大小的日志文件,你用任何编辑器去打开它,都将会很困难。针对这样的大文件解析处理,解决方案是使用多个线程,分割读取指定的大文件。获取我们所需要的信息。不多说,上代码了,有注释可以帮助理解。
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.concurrent.CountDownLatch;
public
class ReadThread
extends Thread{
private
final
int BUFF_LEN =
256;
private
long start;
private
long end;
private RandomAccessFile raf;
private String keywords;
private
int curCount =
0;
private CountDownLatch doneSignal;
public ReadThread(
long start,
long end, RandomAccessFile raf,String keywords,CountDownLatch doneSignal){
this.start = start;
this.end = end;
this.raf = raf;
this.keywords = keywords;
this.doneSignal = doneSignal;
public
void run(){
try {
raf.seek(start);
long contentLen = end - start;
long times = contentLen / BUFF_LEN+
1;
System.out.println(
this.toString() +
" 需要读的次数:"+times);
byte[] buff =
new
byte[BUFF_LEN];
int hasRead =
0;
String result =
null;
for (
int i =
0; i < times; i++) {
hasRead = raf.read(buff);
if (hasRead <
0) {
break;
result =
new String(buff,
"gb2312");
int count =
this.getCountByKeywords(result, keywords);
if(count >
0){
this.curCount += count;
KeyWordsCount kc = KeyWordsCount.getCountObject();
kc.addCount(
this.curCount);
doneSignal.countDown();
}
catch (IOException e) {
e.printStackTrace();
public
long getStart() {
return start;
public
void setStart(
long start) {
this.start = start;
public
long getEnd() {
return end;
public
void setEnd(
long end) {
this.end = end;
public RandomAccessFile getRaf() {
return raf;
public
void setRaf(RandomAccessFile raf) {
this.raf = raf;
public
int getCountByKeywords(String statement,String key){
return statement.split(key).length-
1;
public
int getCurCount() {
return curCount;
public
void setCurCount(
int curCount) {
this.curCount = curCount;
public CountDownLatch getDoneSignal() {
return doneSignal;
public
void setDoneSignal(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.concurrent.CountDownLatch;
public
class MultiReadTest {
public
static
void main(String[] args) {
final
int DOWN_THREAD_NUM =
10;
final String OUT_FILE_NAME =
"d:\\倚天屠龙记.txt";
final String keywords =
"无忌";
CountDownLatch doneSignal =
new CountDownLatch(DOWN_THREAD_NUM);
RandomAccessFile[] outArr =
new RandomAccessFile[DOWN_THREAD_NUM];
long length =
new File(OUT_FILE_NAME).length();
System.out.println(
"文件总长度:"+length+
"字节");
long numPerThred = length / DOWN_THREAD_NUM;
System.out.println(
"每个线程读取的字节数:"+numPerThred+
"字节");
long left = length % DOWN_THREAD_NUM;
for (
int i =
0; i < DOWN_THREAD_NUM; i++) {
outArr[i] =
new RandomAccessFile(OUT_FILE_NAME,
"rw");
if (i !=
0) {
if (i == DOWN_THREAD_NUM -
1) {
new ReadThread(i * numPerThred, (i +
1) * numPerThred
+ left, outArr[i],keywords,doneSignal).start();
}
else {
new ReadThread(i * numPerThred, (i +
1) * numPerThred,
outArr[i],keywords,doneSignal).start();
}
catch(Exception e){
e.printStackTrace();
try {
doneSignal.await();
}
catch (InterruptedException e) {
e.printStackTrace();
KeyWordsCount k = KeyWordsCount.getCountObject();
System.out.println(
"指定关键字出现的次数:"+k.getCount());
public
static
synchronized KeyWordsCount getCountObject(){
if(kc ==
null){
kc =
new KeyWordsCount();
return kc;
public
synchronized
void addCount(
int count){
System.out.println(
"增加次数:"+count);
this.count += count;
public
int getCount() {
return count;
public
void setCount(
int count) {
this.count = count;
运行结果如下:
文件总长度:2012606字节
每个线程读取的字节数:201260字节
Thread[Thread-0,5,main] 需要读的次数:787
Thread[Thread-1,5,main] 需要读的次数:787
Thread[Thread-2,5,main] 需要读的次数:787
Thread[Thread-3,5,main] 需要读的次数:787
Thread[Thread-4,5,main] 需要读的次数:787
Thread[Thread-5,5,main] 需要读的次数:787
Thread[Thread-6,5,main] 需要读的次数:787
Thread[Thread-7,5,main] 需要读的次数:787
Thread[Thread-8,5,main] 需要读的次数:787
Thread[Thread-9,5,main] 需要读的次数:787
增加次数:0
增加次数:146
增加次数:432
增加次数:539
增加次数:587
增加次数:717
增加次数:631
增加次数:467
增加次数:665
增加次数:538
指定关键字出现的次数:4722
我用10个线程去解析金庸大师写的《倚天屠龙记》,“无忌”这个词在这部小说中一共出现了4722次。实在找不到再大一些的文件了。倚天屠龙记.txt的大小4M出头。
关于CountDownLatch类的作用说明:
在API文档中,已经说明是一个辅助类。用于控制主线程与子线程之间切换的一个工具类。用法网上去搜下。ITEYE里也有人讨论过。我在这里使用它解决这样的问题:
在确保10个线程都完成文件的解析工作后,系统调用主线程做剩下该做的事情,即:输出“出现的次数”。
不确保这点的话,会导致执行完第4个线程,后面的线程还没开始,系统已经做最后一步输出统计结果,这样就达不到我们要的效果。这里解决方案有另一个简单的,自己写个计数器,从10记到1,10个线程嘛。这个看个人喜好吧。
原文:http://babystudyjava.iteye.com/blog/1732814