Thread Example

Задача поработать с потоками и проблемой конкурентного доступа: будем в два потока писать файл и одним потоком читать.

Создадим проект ParallelFileExample из которого порадим два потока Writer на запись и один Reader на чтение. Все потоки синхронизуются по экземпляру класса FileWorker (важно, что синхронизоваться надо по единственному экземпляру класса, т.е. в Writer и Reader надо передать заранее созданный экземпляр FileWorker). В классе FileWorker реализовано как чтение, так и запись в файл.

package jperm; /** * * @author ars */ public class ParallelFileExample {

public static void main(String[] args) { // TODO code application logic here FileWorker worker = new FileWorker; worker.setFilePath("C:\\temp\\file.txt"); Writer writer1 = new Writer(worker,"1"); Writer writer2 = new Writer(worker,"2"); Reader reader = new Reader(worker); Thread t1 = new Thread(writer1); Thread t2 = new Thread(writer2); Thread t3 = new Thread(reader); t3.setDaemon(true); t1.start; t3.start; t2.start; } }

Класс Writer:

/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package jperm;

import java.io.IOException;

public class Writer implements Runnable { private boolean stopFlag = false; private int count; private String threadName; private FileWorker fileWorker;

public String getThreadName { return threadName; }

public void setThreadName(String threadName) { this.threadName = threadName; }   public Writer(FileWorker fileWorker, String threadName ) {     // constructor this.fileWorker = fileWorker; setThreadName(threadName); }

public boolean isStopFlag { return stopFlag; }

public void setStopFlag(boolean stopFlag) { this.stopFlag = stopFlag; }

public int getCount { return count; }

public void setCount(int count) { this.count = count; }   @Override public void run { while (!isStopFlag) { try { writeMessage; } catch (InterruptedException ex) { System.out.println(ex); setStopFlag(true); } catch (IOException ex) { System.out.println(ex); setStopFlag(true); }       }    }    public void finish { setStopFlag(true); }   protected void writeMessage throws InterruptedException, IOException  { synchronized (fileWorker) {    // синхронизируемся по объекту FileWorker while ( !fileWorker.isCanWrite ) { fileWorker.wait; }           if (fileWorker.isCanWrite) { count++; fileWorker.write(getThreadName + " write: "+String.valueOf(getCount)); fileWorker.notifyAll; }               //Thread.sleep(10);  // что-то делаем if (getCount>=3000) { setStopFlag(true); }       }     } }

Класс Reader:

/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package jperm; import java.io.IOException;

public class Reader implements Runnable { private boolean stopFlag = false; private int numberLines; private int nowNumberLines; private FileWorker fileWorker; public Reader(FileWorker fileWorker) {    // constructor this.fileWorker = fileWorker; }

public int getNumberLines { return numberLines; }

public void setNumberLines(int numberLines) { this.numberLines = numberLines; }

public boolean isStopFlag { return stopFlag; }

public void setStopFlag(boolean stopFlag) { this.stopFlag = stopFlag; }   public void finish { setStopFlag(true); }   @Override public void run { while (!isStopFlag) { try { printMessage; } catch (InterruptedException ex) { System.out.println(ex); setStopFlag(true); } catch (IOException ex) { System.out.println(ex); setStopFlag(true); }       }    }    protected void printMessage throws InterruptedException, IOException  { synchronized (fileWorker) {    // синхронизируемся по объекту FileWorker while ( !fileWorker.isCanWrite ) { System.out.println("print is wait....................."); fileWorker.wait; }           if (fileWorker.isCanWrite) { System.out.println("Число строк было "+numberLines); this.nowNumberLines = fileWorker.getNumberLines; if (nowNumberLines == numberLines) { System.out.println("Число строк стало "+nowNumberLines+", а было "+numberLines+" и не изменилось, выходим.=========================================="); setStopFlag(true); fileWorker.notifyAll; }               else { System.out.println("reading is "+nowNumberLines+" lines=========================================="); this.setNumberLines(nowNumberLines); fileWorker.notifyAll; fileWorker.wait; }               //Thread.sleep(1000); }

}    } }

FileWriter:

/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package jperm;

import java.io.*; import java.util.Scanner;

// Это общий класс, через него пишем и читаем данные и по нему выполняем блокировку в синхроблоке public class FileWorker {

private FileWriter filewriter; private boolean canWrite;          // сюда пишем блокировку, но эта штука не особо и нежна private String filePath;

public String getFilePath { return filePath; }

public void setFilePath(String filePath) { this.filePath = filePath; }

public void setCanWrite(boolean canWrite) { this.canWrite = canWrite; }   public boolean isCanWrite { return true; }   // записывает текс в файл public void write(String text) throws IOException { setCanWrite(false); System.out.println(text); CharSequence cs = text+"\r\n"; try { filewriter = new FileWriter(getFilePath,true); filewriter.append(cs); filewriter.flush; filewriter.close; }       catch (IOException e) { System.out.println("Не смогли записать в файл."); }       catch (Exception e) { System.out.println("file write error "+ e.toString); }       setCanWrite(true); }   // возвращает количество строк в файле public int getNumberLines throws FileNotFoundException,IOException { FileReader fin = new FileReader(getFilePath); Scanner s = new Scanner(fin); int i=0; while(s.hasNext) { s.nextLine; i++; }       s.close; fin.close; return i;   } }