前言
- 本博客文章只有代码块,一些输出和 try…catch 等内容没有写在这里。
- 本博客文章的目的是熟悉 多线程 的操作,Java新手,如有不妥之处请指正!
- 本文的基础是我的这篇博客,改动了最后字符串查找部分。生成字符串文件、插入子串部分的瓶颈在于IO,就没改动了。
原版代码
long n = 0;
while (true) {
int len;
if (n == 0) {
len = fr.read(cbuf);
} else {
for (int i = 0; i < maxLen; ++i) {
cbuf[i] = cbuf[bufLen - maxLen + i];
}
len = fr.read(cbuf, maxLen, bufLen - maxLen);
}
if (len == -1) break;
for (int i = 0; i < subStrBuf.length; ++i) {
if (indexs[i] == -1) {
int tempIndex = Find(cbuf, subStrBuf[i]);
if (tempIndex != -1) {
indexs[i] = n + tempIndex;
}
}
}
n += len;
}
将16至26行代码重写为
for (int i = 0; i < subStrBuf.length; ++i) {
if (indexs[i] == -1) {
finds[i] = new FindThread(cbuf, subStrBuf[i], indexs, i, n);
finds[i].start();
}
}
for (int i = 0; i < finds.length; ++i) {
if (finds[i].isAlive()) {
finds[i].join();
}
}
查找线程的定义
class FindThread extends Thread {
private char[] str;
private char[] subStr;
private long[] indexs;
private int p;
private long baseIndex;
public FindThread(char[] str, char[] subStr, long[] indexs, int p, long baseIndex) {
this.str = str;
this.subStr = subStr;
this.indexs = indexs;
this.p = p;
this.baseIndex = baseIndex;
}
@Override
public void run() {
for (int i = 0; i < this.str.length; ++i) {
int j;
for (j = 0; j < this.subStr.length; ++j) {
if (i + j >= this.str.length) {
this.indexs[this.p] = -1;
return;
}
if (this.str[i + j] != this.subStr[j]) break;
}
if (j == this.subStr.length) {
this.indexs[this.p] = this.baseIndex + i;
return;
}
}
this.indexs[this.p] = -1;
return;
}
}
感言
- 升级前查找需要11分钟,升级后只需6分钟,效率提升明显。
- 这里用的查找算法仍然是朴素字符串查找算法,时间复杂度较高。然而我发现,时间复杂度更低的sunday算法所用时间比朴素字符串查找还要长很多。仔细分析才发现,原因是我的数据太极端。80亿长的字符串中,只有子串是字母,其它字符全是数字,这样一来,朴素字符串查找算法反而成为了速度最快的一种算法,呵呵。