java中多執行緒讀取同一個檔案的不同位置,多執行緒讀取檔案
阿新 • • 發佈:2019-01-29
今天遇到一個問題,需要多個執行緒讀取同一個檔案的不同位置,提高效率,寫程式碼驗證了一下,把結果記錄下來。
首先我們寫個檔案,然後多執行緒讀取,以下是我實驗的程式碼:
package com.alibaba.middleware.race;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Test2 {
public static void main(String[] args) throws IOException {
byte[] th1 = "執行緒1" .getBytes();
byte[] th2 = "執行緒2".getBytes();
byte[] th3 = "執行緒3".getBytes();
final int len = th1.length;
final RandomAccessFile raf = new RandomAccessFile(
"F:/tianchi/index.data", "rw");
raf.seek(1);
raf.write(th1);
raf.seek(200);
raf.write(th2);
raf.seek(300 );
raf.write(th3);
Runnable runnable1 = new Runnable() {
@Override
public void run() {
while (true) {
byte[] b = new byte[len];
try {
raf.seek(1);
raf.read(b);
if ("執行緒1".equals(new String(b))) {
System.out.println("ok");
} else {
System.out.println("執行緒1-" + new String(b));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Runnable runnable2 = new Runnable() {
@Override
public void run() {
while (true) {
try {
byte[] b = new byte[len];
raf.seek(200);
raf.read(b);
if ("執行緒2".equals(new String(b))) {
System.out.println("ok");
} else {
System.out.println("執行緒2-" + new String(b));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Runnable runnable3 = new Runnable() {
@Override
public void run() {
while (true) {
try {
byte[] b = new byte[len];
raf.seek(300);
raf.read(b);
if ("執行緒3".equals(new String(b))) {
System.out.println("ok");
} else {
System.out.println("執行緒3-" + new String(b));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
for (int i = 0; i < 20; i++) {
new Thread(runnable1).start();
new Thread(runnable2).start();
new Thread(runnable3).start();
}
System.out.println("主執行緒完了");
}
}
測試結果如下,會出現這樣的問題:
ok
執行緒3-
執行緒1-執行緒3
ok
ok
說明,多個執行緒讀取同一個檔案,不加鎖,是會出錯的。
然後我們做如下改進。
程式碼:
package com.alibaba.middleware.race;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Test2 {
public static void main(String[] args) throws IOException {
byte[] th1 = "執行緒1".getBytes();
byte[] th2 = "執行緒2".getBytes();
byte[] th3 = "執行緒3".getBytes();
final int len = th1.length;
final RandomAccessFile raf = new RandomAccessFile(
"F:/tianchi/index.data", "rw");
raf.seek(1);
raf.write(th1);
raf.seek(200);
raf.write(th2);
raf.seek(300);
raf.write(th3);
Runnable runnable1 = new Runnable() {
@Override
public void run() {
while (true) {
byte[] b = new byte[len];
try {
synchronized (raf) {
raf.seek(1);
raf.read(b);
}
if ("執行緒1".equals(new String(b))) {
System.out.println("ok");
} else {
System.out.println("執行緒1-" + new String(b));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Runnable runnable2 = new Runnable() {
@Override
public void run() {
while (true) {
try {
byte[] b = new byte[len];
synchronized (raf) {
raf.seek(200);
raf.read(b);
}
if ("執行緒2".equals(new String(b))) {
System.out.println("ok");
} else {
System.out.println("執行緒2-" + new String(b));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Runnable runnable3 = new Runnable() {
@Override
public void run() {
while (true) {
try {
byte[] b = new byte[len];
synchronized (raf) {
raf.seek(300);
raf.read(b);
}
if ("執行緒3".equals(new String(b))) {
System.out.println("ok");
} else {
System.out.println("執行緒3-" + new String(b));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
for (int i = 0; i < 20; i++) {
new Thread(runnable1).start();
new Thread(runnable2).start();
new Thread(runnable3).start();
}
System.out.println("主執行緒完了");
}
}
對檔案的訪問加一個鎖,這樣就可以了,測試結果是對的,我就不貼了。