1. 程式人生 > >java中多執行緒讀取同一個檔案的不同位置,多執行緒讀取檔案

java中多執行緒讀取同一個檔案的不同位置,多執行緒讀取檔案

今天遇到一個問題,需要多個執行緒讀取同一個檔案的不同位置,提高效率,寫程式碼驗證了一下,把結果記錄下來。

首先我們寫個檔案,然後多執行緒讀取,以下是我實驗的程式碼:

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("主執行緒完了");

    }

}

對檔案的訪問加一個鎖,這樣就可以了,測試結果是對的,我就不貼了。