package IO;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;

public class Io extends Thread{

    private StringBuffer text = new StringBuffer();
    private long start;
    private CountDownLatch count = new CountDownLatch(0);

    public Io(CountDownLatch count){
        this.count = count;
    }
    public FileReader reader;
    {
        try {
            reader = new FileReader("D:\\seldom\\Red.Alert.2.Yuris.Revenge.LAN.Green." +
                    "Edition-ALI213\\Red.Alert.2.Yuris.Revenge.CHS.Green.Edition-ALI213\\creditsmd.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public void setStart(long start){
        this.start = start;
    }

    @Override
    public void run() {
        char[] store = new char[10];
        try {
            long real = reader.skip(this.start);
            for (int i = 0; i < 50; i++){
                if (reader.read(store) > 0) {
                    text.append(store);
                    store = new char[10];
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.count.countDown();
        System.out.println(this.start/500 + "线程执行完毕");
    }

    public StringBuffer getText(){
        return text;
    }

    public static void main(String[] args) throws InterruptedException {
        Io[] thread = new Io[10];
        final CountDownLatch count = new CountDownLatch(10);
        for (int i = 0; i < 10; i++){
            thread[i] = new Io(count);
            thread[i].setStart(i*500);
        }

        for (Io i: thread){
            i.start();
        }
        count.await();

        for (int i = 0; i < 10; i++){
            System.out.println(i + "---------------------------------------------------------------");
            System.out.println(thread[i].getText());
        }

    }
}

读取与多线程写起来其实很简单,不过处理时遇到了意想不到的麻烦。
首先是run方法没有返回值,所以只能另写一个返回获取读取数据的方法。
然而虽然read方法是阻塞的,但是线程本身不是阻塞的,所以线程启动之后返回获取数据的方法会立即执行,所以事实上还没等程序从文件中获取数据,方法已经将获取的数据返回到了main中,所以返回值会是空。
原计划重载run方法,使其直接返回数据,但事实上start方法只调用无参数的run方法,而且只有start调用的run方法才是异步的,也就意味着重载的run方法是同步的且毫无意义的。
最终我在类中声明了一个静态的变量用于存储数据,不过紧接着又遇到了两个问题,一个是线程顺序问题,线程启动的顺序一定,但结束的顺序不一定,这就导致了数据顺序可能会发生错乱,另一个问题是主线程最终要等所有子线程结束之后才能输出数据,否则输出的数据会不全。
对于第二个问题查阅后发现多种解决方式,最简单的就是直接让主线程休眠一会儿,还有就是CountDownLatch用于线程同步的类以及线程池。理论上都能解决第二个问题,因为sleep复用性低,而线程池又不熟悉所以这里采用的是CountDownLatch类解决。至于顺序问题,去掉了之前的静态变量存储,数据拼接不再是边获取边拼接,而是改为了所有子线程都结束之后再拼接。目前就是这个情况,以后还有缓冲流,nio库,线程池要试,这次就先到这里。
Ps:多线程读取文件其实卵用没有,某种程度上来说反倒是会浪费资源,所以就是写着玩玩。( ̄▽ ̄)*