Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多线程文件读取_Java_Multithreading_File - Fatal编程技术网

Java 多线程文件读取

Java 多线程文件读取,java,multithreading,file,Java,Multithreading,File,我试图用Java编写代码,通过几个线程读取一个文件,并计算其中的字数。每个线程应该读不同的行。它可以很好地计算字数(当我让1个线程运行时),但我的线程正在读取同一行,同时递增行计数器。我确信read方法中的synchronized关键字会修复它,但它没有。我该怎么做才能修好它 import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.*; impor

我试图用Java编写代码,通过几个线程读取一个文件,并计算其中的字数。每个线程应该读不同的行。它可以很好地计算字数(当我让1个线程运行时),但我的线程正在读取同一行,同时递增行计数器。我确信read方法中的
synchronized
关键字会修复它,但它没有。我该怎么做才能修好它

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;


public class WordCounterr implements Runnable {
    private static Hashtable<String, Integer> ht = new Hashtable<String, Integer>();
    private int lineCounter;
    private String path;
    private int tNumber;
    //private final AtomicInteger whichLine = new AtomicInteger();
    private static int whichLine;
    private static boolean flag;

    public WordCounterr(String path,int num){
        lineCounter = 0;
        //whichLine = 0;
        flag= false;
        this.path=path;
        tNumber = num;
    }

    public void countWords(String s) throws IOException{
        char[] c = s.toCharArray();
        String str="";  
        char ch;        
        for(int k=0;k<c.length;k++){                        

            ch=c[k];                    
            if((ch>40 && ch<91) ||(ch>96 && ch<123)){       
                if(ch>40 && ch<91)
                    ch+=32;             
                str+=ch;
            }           
            else if(ch==32 ||k==c.length-1){
                if(str.length()>1){ //sprawdzamy czy funkcja znalazla juz 
                    if(ht.containsKey(str))     //takie slowo               
                        ht.put(str,ht.get(str)+1); //znalazla - powiekszamy wartosc przy kluczu
                    else
                        ht.put(str,1);  //nie znalazla - dodajemy slowo do Hashtable            

                }
                str="";
            }
        }
    }

    public synchronized void read(String path) throws IOException{  
        BufferedReader buf=new BufferedReader(new FileReader(path));

        String linia ;
        for(int i=0;i<whichLine;i++){
            linia=buf.readLine();
        }

        if((linia=buf.readLine())!=null){
            System.out.println(linia);
            countWords(linia);
            lineCounter++;
            System.out.println("watek nr:"+tNumber+"ktora linia:"+whichLine);               
            whichLine++;
            /*try{
                    Thread.sleep(100);

                }catch(InterruptedException el){
                    System.out.println(el.toString());
                }*/
        } else
            setFlag(true);

        buf.close();    //pamietamy o zamknieciu pliku

    }

    public synchronized void print(){
        if(getFlag()){
            setFlag(false);         
            System.out.println(ht);
        }   
        System.out.println("watek nr: "+tNumber+", przeanalizowano "+ lineCounter+ "linii tekstu");
    }

    public void setFlag(boolean val){
        flag=val;
    }

    public boolean getFlag(){
        return flag;
    }

    @Override
    public void run() {
        try{    

            while(getFlag()==false) {   
                read(path);
                Thread.yield(); //let other thread read
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }catch(IOException ex){
            System.out.println(ex.toString());
        }//catch(InterruptedException el){
        //  System.out.println(el.toString());
        //}     
        print();
    }   

    public static void main(String[] args) throws IOException, InterruptedException{
        String path = args[0];
        int tNum = Integer.parseInt(args[1]);

        Thread[] thread = new Thread[tNum]; // tablica w?tków
        for (int i = 0; i < tNum; i++){
            thread[i] =new Thread(new WordCounterr(path,i));
        }   

        for (int i = 0; i < tNum; i++) 
            thread[i].start();
        }
}
导入java.io.BufferedReader;
导入java.io.FileReader;
导入java.io.IOException;
导入java.util.*;
导入java.util.concurrent.AtomicInteger;
公共类WordCounter实现可运行{
私有静态哈希表ht=新哈希表();
专用内线计数器;
私有字符串路径;
私人国际号码;
//private final AtomicInteger,其行=新的AtomicInteger();
私有静态输入线;
私有静态布尔标志;
公共字计数器(字符串路径,int num){
lineCounter=0;
//其中直线=0;
flag=false;
this.path=path;
tNumber=num;
}
公共void countWords(字符串s)引发IOException{
char[]c=s.toCharArray();
字符串str=“”;
char ch;
对于(int k=0;k40&&ch96&&ch40&&ch1){//sprawdzamy czy funkcja znalazla juz
if(ht.containsKey(str))//takie slowo
ht.put(str,ht.get(str)+1);//znalazla-powiekszamy-wartosc-przy-kluczu
其他的
ht.put(str,1);//nie znalazla-dodajemy slowo do哈希表
}
str=“”;
}
}
}
公共同步的无效读取(字符串路径)引发IOException{
BufferedReader buf=新的BufferedReader(新文件读取器(路径));
弦纹;

对于(int i=0;i同步修饰符的定义如下:
不可能在同一对象上交替调用两个同步方法。

在每个
线程中调用方法
read

但是,您没有调用相同的
read
方法,因为您正在将
wordcounter
new实例传递给每个新的
线程
。这意味着您在不受同步修改器影响的不同对象上调用该方法

要修复此问题,请尝试:

WordCounterr reader = new WordCounterr(path,0); //I changed i to 0 because it can't differentiate between threads with a simple int. This is because each Thread now references the same object.
Thread[] thread = new Thread[tNum]; // tablica w?tków
for (int i = 0; i < tNum; i++){
    thread[i] =new Thread(reader);
} 
WordCounter reader=new WordCounter(path,0);//我将I更改为0,因为它不能用简单的int区分线程。这是因为每个线程现在引用相同的对象。
线程[]线程=新线程[tNum];//tablica w?tków
对于(int i=0;i
而不是:

Thread[] thread = new Thread[tNum]; // tablica w?tków
for (int i = 0; i < tNum; i++){
    thread[i] =new Thread(new WordCounterr(path,i));
} 
Thread[]Thread=新线程[tNum];//tablica w?tków
对于(int i=0;i

我希望这会有所帮助:)

我猜它仍然会低效地读取文件内容。 尝试更改同步点。它应该放在read方法中。此方法读取整个文件内容。而不是仅尝试同步读取此文件的下一行。您可以通过将相同的reader文件实例放置到每个WordCounter实例,并仅同步将指针移动到t的下一行读取内容的过程来实现他的行。行中的字数计算可以在不同步的情况下完成,并且只应同步更新哈希表。 并行读取文件内容可以按以下方式同步:

static class Reader implements Runnable {
    int lineReaded = 0;
    final Scanner scanner;

    Reader(Scanner scanner) {
        this.scanner = scanner;
    }

    public void run() {
        boolean hasNext = true;
        while (hasNext) {
            hasNext = false;
            synchronized (scanner) {
                if (scanner.hasNext()) {
                    hasNext = true;
                    String line = scanner.nextLine();
                    ++lineReaded;
                }
            }
            try {
                Thread.sleep((long) (Math.random() * 100));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

是的,这很有帮助。但现在我有一个object WordCounter实例,看不到每个线程分析了多少行:(知道如何同步WordCounter类的两个或多个实例吗?@stackwack要做到这一点,我建议看gauee的答案,它同步读取器而不是方法。