Read file with multiple threads - java

Is it possible to read a text file by running several threads, so that received line contains information about the thread that read this line?
For now, i can read with one thread:
public class Test {
public static void main(String[] args) throws InterruptedException {
Deque<String> deque = new LinkedList<>();
for (int i = 0; i < 4; i++) {
new Thread(new SubReadThread(deque)).start();
}
new Thread(new WriteThread(deque)).start();
}
}
class SubReadThread implements Runnable {
private final Deque<String> deque;
public SubReadThread(Deque<String> deque) {
this.deque = deque;
}
#Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("list.txt"), "UTF8"));
String line = null;
String newLine;
while (true) {
synchronized (deque) {
if (deque.size() < 1) {
line = br.readLine();
newLine = "#" + (Thread.currentThread().getId() - 9) + " " + line;
deque.addLast(newLine);
deque.notify();
} else {
deque.wait();
}
if (line == null) {
break;
}
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
class WriteThread implements Runnable {
private final Deque<String> deque;
private List<String> list = new ArrayList<>();
public WriteThread(Deque<String> deque) {
this.deque = deque;
}
#Override
public void run() {
String line;
while (true) {
synchronized (deque) {
if (deque.size() > 0) {
if ((line = deque.pollFirst()).contains("null")) {
break;
} else {
list.add(line);
deque.notifyAll();
}
} else {
try {
deque.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
for(String s : list) {
System.out.println(s);
}
}
}
And expected output something like this:
#3 line1
#1 line2
#4 line3
#2 line4
...............
UPDATE All that was needed to work properly, move BufferedReader to main method and pass its object to the constructor.

Related

Concurrent method works much longer than simple method. Why?

I wrote simple method for reading one file and writing into 2 files. Also I wrote this method with 3 threads, where the first thread reads line-by-line file, the second and the third write readed line into own file. My parallel version of method works in 30 times longer than simple sequential method. Please, help to understand what I do wrong, and how I should do this method to not shooting in my leg)))
private static class Tee {
private BufferedReader reader;
private PrintWriter fWriter;
private PrintWriter sWriter;
volatile boolean done;
String buffer;
volatile int readCount;
volatile int firstWriteCount;
volatile int secondWriteCount;
public Tee(BufferedReader reader, PrintWriter fWriter, PrintWriter sWriter) {
this.reader = reader;
this.fWriter = fWriter;
this.sWriter = sWriter;
}
public void teeWhileInsideCo() throws InterruptedException {
Thread reader = new Thread(new LineReader());
Thread fWriter = new Thread(new LineWriter(this.fWriter, 0));
Thread sWriter = new Thread(new LineWriter(this.sWriter, 1));
reader.start();
fWriter.start();
sWriter.start();
reader.join();
fWriter.join();
sWriter.join();
}
private class LineReader implements Runnable {
#Override
public void run() {
String line;
while (true) {
try {
line = reader.readLine();
} catch (IOException e) {
line = null;
}
while (readCount != firstWriteCount || readCount != secondWriteCount) {
}
if (line == null) {
done = true;
break;
}
buffer = line;
readCount++;
}
}
}
private class LineWriter implements Runnable {
private PrintWriter writer;
private int number;
public LineWriter(PrintWriter writer, int n) {
System.out.println(Tee.this);
this.writer = writer;
this.number = n;
}
#Override
public void run() {
while (true) {
while (!done && ((number == 0 ? firstWriteCount : secondWriteCount) == readCount)) {
}
if (done) {
break;
}
writer.println(buffer);
if (number == 0) {
firstWriteCount++;
} else {
secondWriteCount++;
}
}
writer.flush();
}
}
}

Thread not starting?

Im working on a project and is confused at why the thread wont start when I call .start()
int count = 0;
while (count < urls.length) {
try {
Thread thread = new Thread(new read(urls[count]));
thread.start();
} catch (Exception e) {
}
count++;
}
but if I add
public void start() {
run();
}
in the read class and change the code to
int count = 0;
while (count < urls.length) {
try {
read thread = new read(urls[count]);
thread.start();
} catch (Exception e) {
}
count++;
}
it works fine.
EDIT : here is my read class code
its reading data from url and calling some other methods i have in the class to store data etc.
public class read implements Runnable {
URL url;
public read(String str) throws IOException {
url = new URL(str);
}
public void run() {
try {
URLConnection connect = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connect.getInputStream()));
String input;
String[] temp;
int x = 0;
while (x < 10) {
reader.readLine();
x++;
}
while ((input = reader.readLine()) != null) {
temp = input.split(" ");
temp[2].replaceAll("<br>", "");
String name = temp[0];
int flightNum = Integer.parseInt(temp[1]);
String des = temp[2];
if (Airport.containsKey(flightNum) != true) {
addFlight(flightNum, des);
addPassengerReservation(flightNum, name);
}
else {
addPassengerReservation(flightNum, name);
}
}
reader.close();
}catch (Exception e) {}
}
}
You should make a class implementing Runnable (ClassA), and override the
public void run()
method. From your "main" program, you should call:
Thread th = new Thread(new ClassA());
th.start();
You should never override the start method, or call th.run(). Calling the start method will do some "behind the scenes" work, then call your Runnable Object's run() method for you.
Thread.start() code registers the Thread with scheduler and the scheduler calls the run() method.You need to override the run() method.No need to call run() implicitly.

Java run linux(raspbian) command(omxplayer) and get output

I create a program as below to execute a linux (raspbian) command: "omxplayer".
But I don't know why I cannot get output from omxplayer as the time I type it into command line and hit Enter.But the output only show at the end of the video.
So I want to get the output immediately after I type "omxplayer [video_name]" and hit "Enter" in my program.
Just like the command line (terminal) work when I type directly into it in linux.
This is my code:
public class testprog {
public static void main(String args[]) throws IOException {
String in = "";
while(in!="exit")
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
in = reader.readLine();
runCommand(in);
}
}
public static void runCommand(String command)
{
String s;
Process p;
try {
System.out.println("run command " + command);
p = Runtime.getRuntime().exec(new String[]{"bash", "-c",command});
MyInputStreamReader reader1 = new MyInputStreamReader(p.getInputStream());
reader1.setTag("in");
reader1.start();
MyInputStreamReader reader2 = new MyInputStreamReader(p.getErrorStream());
reader2.setTag("in");
reader2.start();
p.waitFor();
System.out.println ("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {}
}
}
class MyInputStreamReader extends Thread{
boolean isStop = false;
ReadEventHandler handler;
String tag;
InputStream in;
public MyInputStreamReader(InputStream in)
{
this.in = in;
}
public void setHandler(ReadEventHandler handler) {
this.handler = handler;
}
public void setTag(String tag)
{
this.tag = tag;
}
public void run()
{
byte[] buff = new byte[8192];
while (true) {
//String line;
try {
int len = in.read(buff);
if (len == -1)
{
return;
}
String line = new String(buff, 0, len);
if (handler!=null)
handler.onReceived(line);
System.out.println(tag +" " + line);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void dispose()
{
this.isStop = true;
}
public interface ReadEventHandler
{
void onReceived(String line);
}
}
Any response is highly appreciated. Thanks
Did you checked this?
http://javedmandary.blogspot.com/2014/01/firing-up-raspberry-pi-omxplayer-using.html
I guess there is the code you're looking for.

How to organize multithreadings work with queue?

I'm begginer and keep yourself in hends.
I need to do organize multithreadings find in files:
User input where find(path) and what find(word);
First thread finds .txt files in folder and add result to queue;
When queue has some file => Second thread start find in this file
what need to find(word).
If was finded success would show path this
file + how offen times this word meets in file.
Qestions:
Can we use ArrayList (or exist any alternatives) for queue which works with few threads?
How to do if queue is empty, Second thread don't start but waits when First finded need file?
Need we use synchronized for this task and inherited MultiThreadingSearch(or better to use composition)?
Code:
import java.util.*;
import java.io.*;
class ArrayListOfFiles {
private Node first, last;
private class Node {
String item;
Node next;
}
public boolean isEmpty() {
return first == null;
}
public synchronized void enqueue(String item) {
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty())
first = last;
else
oldlast.next = last;
}
public synchronized String dequeue() {
String item = first.item;
first = first.next;
if (isEmpty())
last = null;
return item;
}
}
class FolderScan extends MultiThreadingSearch implements Runnable {
FolderScan(String path, String whatFind) {
super(path, whatFind);
}
#Override
public void run() {
findFiles(path);
}
ArrayListOfFiles findFiles(String path) {
File root = new File(path);
File[] list = root.listFiles();
for (File titleName : list) {
if (titleName.isDirectory()) {
findFiles(titleName.getAbsolutePath());
} else {
if (titleName.getName().toLowerCase().endsWith((".txt"))) {
textFiles.enqueue(titleName.getName());
}
}
}
return textFiles;
}
}
class FileScan extends MultiThreadingSearch implements Runnable {
Scanner scanner = new Scanner((Readable) textFiles);
Set<String> words = new HashSet<String>();
int matches = 0;
FileScan(String file, String whatFind) {
super(file, whatFind);
Thread wordFind = new Thread();
wordFind.start();
}
#Override
public void run() {
while (scanner.hasNext()) {
String word = scanner.next();
words.add(word);
}
if (words.contains(this.whatFind)) {
System.out.println("File:" + this.path);
matches++;
}
System.out.println(matches);
}
}
public class MultiThreadingSearch {
String path;
String whatFind;
ArrayListOfFiles textFiles;
MultiThreadingSearch(String path, String whatFind) {
this.path = path;
this.whatFind = whatFind;
this.textFiles = new ArrayListOfFiles();
Thread pathFind = new Thread(new FolderScan(path, whatFind));
// pathFind.start();
if (!textFiles.isEmpty()) {
#SuppressWarnings("unused")
FileScan fileScan = new FileScan(textFiles.dequeue(), whatFind);
}
}
// ask user about input
public static void askUserPathAndWord() {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(System.in));
String path;
String whatFind;
try {
System.out.println("Please, enter a Path and Word"
+ "(which you want to find):");
System.out.println("Please enter a Path:");
path = bufferedReader.readLine();
System.out.println("Please enter a Word:");
whatFind = bufferedReader.readLine();
if (path != null && whatFind != null) {
new MultiThreadingSearch(path, whatFind);
System.out.println("Thank you!");
} else {
System.out.println("You did not enter anything");
}
} catch (IOException | RuntimeException e) {
System.out.println("Wrong input!");
e.printStackTrace();
}
}
public static void main(String[] args) {
askUserPathAndWord();
}
}
I got Exception in thread "main" java.lang.StackOverflowError from this code.
How able to solve this task?
Thanks,
Nazar.
Check BlockingQueue it does exactly what you need. Thread can block until some other thread add new item to queue.
As to how decompose you system. I'd do following:
Create class for searching txt files in path. It implements Runnable. You pass path and queue to it. And it searches path for txt files and adds them to the queu.
Create class for searching file content. It implements Runnable. You pass whatFind and queue to it and it takes new file from queue and checks it's content.
Something like:
BlockingQueue<File> queue = new LinkedBlockingQueue<File>();
String path = ...;
String whatFind = ...;
FolderScan folderScan = new FolderScan(path, queue);
FileScan fileScan = new FileScan(whatFind, queue);
Executor executor = Executors.newCachecThreadPool();
executor.execute(folderScan);
executor.execute(fileScan);
If you want FileScan to wait until FolderScan adds something to the queue you can use take method:
BlockingQueue<File> queue;
File toProcess = queue.take(); // this line blocks current thread (FileScan) until someone adds new item to the queue.
After changes:
package task;
import java.util.concurrent.*;
import java.util.*;
import java.io.*;
class FolderScan implements Runnable {
private String path;
private BlockingQueue<File> queue;
private CountDownLatch latch;
private File endOfWorkFile;
FolderScan(String path, BlockingQueue<File> queue, CountDownLatch latch,
File endOfWorkFile) {
this.path = path;
this.queue = queue;
this.latch = latch;
this.endOfWorkFile = endOfWorkFile;
}
public FolderScan() { }
#Override
public void run() {
findFiles(path);
queue.add(endOfWorkFile);
latch.countDown();
}
private void findFiles(String path) {
try {
File root = new File(path);
File[] list = root.listFiles();
for (File currentFile : list) {
if (currentFile.isDirectory()) {
findFiles(currentFile.getAbsolutePath());
} else {
if (currentFile.getName().toLowerCase().endsWith((".txt"))) {
queue.put(currentFile);
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class FileScan implements Runnable {
private String whatFind;
private BlockingQueue<File> queue;
private CountDownLatch latch;
private File endOfWorkFile;
public FileScan(String whatFind, BlockingQueue<File> queue,
CountDownLatch latch, File endOfWorkFile) {
this.whatFind = whatFind;
this.queue = queue;
this.latch = latch;
this.endOfWorkFile = endOfWorkFile;
}
public FileScan() { }
Set<String> words = new HashSet<String>();
int matches = 0;
#Override
public void run() {
while (true) {
try {
File file;
file = queue.take();
if (file == endOfWorkFile) {
break;
}
scan(file);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
latch.countDown();
}
private void scan(File file) {
Scanner scanner = null;
try {
scanner = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException.");
e.printStackTrace();
}
while (scanner.hasNext()) {
String word = scanner.next();
words.add(word);
}
if (words.contains(this.whatFind)) {
matches++;
}
String myStr = String.format("File: %s and the number of matches "
+ "is = %d", file.getAbsolutePath(), matches);
System.out.println(myStr);
matches = 0;
}
// ask user about input
public void askUserPathAndWord() {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(System.in));
String path;
String whatFind;
BlockingQueue<File> queue = new LinkedBlockingQueue<File>();
try {
System.out.println("Please, enter a Path and Word"
+ "(which you want to find):");
System.out.println("Please enter a Path:");
path = bufferedReader.readLine();
System.out.println("Please enter a Word:");
whatFind = bufferedReader.readLine();
if (path != null && whatFind != null) {
File endOfWorkFile = new File("GameOver.tmp");
CountDownLatch latch = new CountDownLatch(2);
FolderScan folderScan = new FolderScan(path, queue, latch,
endOfWorkFile);
FileScan fileScan = new FileScan(whatFind, queue, latch,
endOfWorkFile);
Executor executor = Executors.newCachedThreadPool();
executor.execute(folderScan);
executor.execute(fileScan);
latch.await();
System.out.println("Thank you!");
} else {
System.out.println("You did not enter anything");
}
} catch (IOException | RuntimeException e) {
System.out.println("Wrong input!");
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("Interrupted.");
e.printStackTrace();
}
}
/**
* #param args
*/
public static void main(String[] args) {
new FileScan().askUserPathAndWord();
}
}
This may not sound too constructive, but you can either fix that code or read something like this first and then throw away your code.
Stackoverflow usually results from a recursion running deeper than expected. Make sure there is some condition in you recursive method that stops recursion.

notifyAll() method is not working in my code

I am trying to implement Bully Algorithm in Java using threads.
Here is the code which I have written.
package newbully;
public class NewBully {
public static void main(String[] args) {
int total_processes = 4;
Thread1[] t = new Thread1[total_processes];
for (int i = 0; i < total_processes; i++) {
t[i] = new Thread1(new Process(i+1, i+1), total_processes);
}
try {
Election.initialElection(t);
} catch (Exception e) {
System.out.println("Possibly you are using null references in array");
}
for (int i = 0; i < total_processes; i++) {
new Thread(t[i]).start();
}
}
}
package newbully;
public class Election {
private static boolean pingFlag = false;
private static boolean electionFlag = false;
private static boolean messageFlag = false;
public static boolean isMessageFlag() {
return messageFlag;
}
public static void setMessageFlag(boolean messageFlag) {
Election.messageFlag = messageFlag;
}
public static boolean isPingFlag() {
return pingFlag;
}
public static void setPingFlag(boolean pingFlag) {
Election.pingFlag = pingFlag;
}
public static boolean isElectionFlag() {
return electionFlag;
}
public static void setElectionFlag(boolean electionFlag) {
Election.electionFlag = electionFlag;
}
public static void initialElection(Thread1[] t) {
Process temp = new Process(-1, -1);
for (int i = 0; i < t.length; i++) {
if (temp.getPriority() < t[i].getProcess().getPriority()) {
temp = t[i].getProcess();
}
}
t[temp.pid - 1].getProcess().CoOrdinatorFlag = true;
}
}
package newbully;
public class Process {
int pid;
boolean downflag,CoOrdinatorFlag;
public boolean isCoOrdinatorFlag() {
return CoOrdinatorFlag;
}
public void setCoOrdinatorFlag(boolean isCoOrdinator) {
this.CoOrdinatorFlag = isCoOrdinator;
}
int priority;
public boolean isDownflag() {
return downflag;
}
public void setDownflag(boolean downflag) {
this.downflag = downflag;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public Process() {
}
public Process(int pid, int priority) {
this.pid = pid;
this.downflag = false;
this.priority = priority;
this.CoOrdinatorFlag = false;
}
}
package newbully;
import java.util.*;
import java.io.*;
import java.net.*;
public class Thread1 implements Runnable {
private Process process;
private int total_processes;
ServerSocket[] sock;
Random r;
public Process getProcess() {
return process;
}
public void setProcess(Process process) {
this.process = process;
}
public Thread1(Process process, int total_processes) {
this.process = process;
this.total_processes = total_processes;
this.r = new Random();
this.sock = new ServerSocket[total_processes];
}
private void recovery() {
}
synchronized private void pingCoOrdinator() {
try {
if (Election.isPingFlag()) {
wait();
}
if (!Election.isElectionFlag()) {
Election.setPingFlag(true);
System.out.println("Process[" + this.process.getPid() + "]: Are you alive?");
Socket outgoing = new Socket(InetAddress.getLocalHost(), 12345);
outgoing.close();
Election.setPingFlag(false);
notifyAll();
}
} catch (Exception ex) {
//Initiate Election
System.out.println("process[" + this.process.getPid() + "]: -> Co-Ordinator is down\nInitiating Election");
Election.setElectionFlag(true);
Election.setPingFlag(false);
notifyAll();
}
}
synchronized private void executeJob() {
int temp = r.nextInt(20);
for (int i = 0; i <= temp; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("Error Executing Thread:" + process.getPid());
System.out.println(e.getMessage());
}
}
}
synchronized private boolean sendMessage() {
boolean response = false;
int i = 0;
try {
if (Election.isMessageFlag()) {
wait();
}
Election.setMessageFlag(true);
for (i = this.process.getPid() + 1; i <= this.total_processes; i++) {
try {
Socket electionMessage = new Socket(InetAddress.getLocalHost(), 10000 + i);
System.out.println("Process[" + this.process.getPid() + "] -> Process[" + i + "] responded to election message successfully");
electionMessage.close();
response = true;
} catch (Exception ex) {
System.out.println("Process[" + this.process.getPid() + "] -> Process[" + i + "] did not respond to election message");
}
}
Election.setMessageFlag(false);
notifyAll();
} catch (Exception ex1) {
System.out.println(ex1.getMessage());
}
return response;
}
synchronized private void serve() {
try {
//service counter
ServerSocket s = new ServerSocket(12345);
for (int counter = 0; counter <= 10; counter++) {
Socket incoming = s.accept();
System.out.println("Process[" + this.process.getPid() + "]:Yes");
Scanner scan = new Scanner(incoming.getInputStream());
PrintWriter out = new PrintWriter(incoming.getOutputStream(), true);
if (scan.hasNextLine()) {
if (scan.nextLine().equals("Who is the co-ordinator?")) {
System.out.print("Process[" + this.process.getPid() + "]:");
out.println(this.process);
}
}
if (counter == 10) {//after serving 10 requests go down
this.process.setCoOrdinatorFlag(false);
this.process.setDownflag(true);
try {
incoming.close();
s.close();
sock[this.process.getPid() - 1].close();
Thread.sleep((this.r.nextInt(10) + 1) * 50000);//going down
recovery();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
#Override
public void run() {
try {
sock[this.process.getPid() - 1] = new ServerSocket(10000 + this.process.getPid());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
while (true) {
if (process.isCoOrdinatorFlag()) {
//serve other processes
serve();
} else {
while (true) {
//Execute some task
executeJob();
//Ping the co-ordinator
pingCoOrdinator();
if (Election.isElectionFlag()) {
if (!sendMessage()) {//elect self as co-ordinator
System.out.println("New Co-Ordinator: Process[" + this.process.getPid() + "]");
this.process.setCoOrdinatorFlag(true);
Election.setElectionFlag(false);
break;
}
}
}
}
}
}
}
When I am trying to execute the code out of the 4 threads which I have created some threads are waiting premanently using wait() call. They are not being notified by notifyAll(). Can anyone suggest why this is happening?
Each thread is calling wait() on itself (on its own Thread1 instance). That means that when you call notifyAll() on that same Thread1 instance, only the single Thread1 that is waiting it will be notified, and not all the other threads.
What you have to do is make all your Thread1 objects call wait() on a single, common object, and also call notifyAll() on that same object.
Ofcourse you have to synchronize on the common object when you call wait() or notifyAll() on it; if you don't do that, you'll get an IllegalMonitorStateException.
// Object to be used as a lock; pass this to all Thread1 instances
Object lock = new Object();
// Somewhere else in your code
synchronized (lock) {
lock.wait();
}
// Where you want to notify
synchronized (lock) {
lock.notifyAll();
}
Both notify() (or notifyAll()) and wait() must be written into synchronized block on the same monitor.
For example:
synchronized(myLock) {
wait();
}
..................
synchronized(myLock) {
notifyAll();
}

Categories