I have rewritten this many times but I could not find a solution to this problem for a while. Some other Class writes gps.log file with lines like:
2014-09-02 10:23:13 35.185604 33.859077
2014-09-02 10:23:18 35.185620 33.859048
I am trying to read the last line of the file and update a text field in the user interface. The Thread below is overdriving the CPU into 85-100%.
I keep the file very tiny (100 lines - < 5KB). I have been working with CSV for a long time, and I think reading this file every 3 seconds should not have this footprint on the CPU. Although I have been reading huge CSV files in the past it is the first time I have this issue now that I try to update the User Interface every couple seconds. Am I doing something wrong with how I am updating the text field? Any ideas?
Thanks for looking.
new Thread(new Runnable() {
public void run() {
while (true) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
try {
try { Thread.sleep(3000); } catch (Exception e) { }
BufferedReader gpslog = new BufferedReader(new FileReader("log/gps.log"));
String line = "";
String lastLine = "";
int i=0;
while (line != null) {
i++;
lastLine = line;
line = gpslog.readLine();
}
//System.out.println(lastLine);
gpslog.close();
if (lastLine != null) { txtGPSStatus.setText(lastLine); }
//If more than 100 gps entries, flush the file
if (i>100) {
PrintWriter writer = new PrintWriter("log/gps.log");
writer.close();
}
} catch (IOException e1) {
log.error(e1);
}
}
});
}
}
}).start();
Move
try { Thread.sleep(3000); } catch (Exception e) { }
so it is just after
while(true) {
Then you will run, wait 3 secs, run, etc.
You should get a clear idea of what should be done by the background thread and what the UI thread is for!
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() {
public void run() {
try {
while (true) {
updateLog();
Thread.sleep(3000);
}
} catch (InterruptedException ex) {
// restore interruption flag
Thread.currentThread().interrupt();
}
}
});
private void updateLog() {
String lastLine = readLastLogLine();
Display.getDefault().syncExec(new Runnable() {
public void run() {
txtGPSStatus.setText(lastLine);
}
});
}
Related
I've written an endless loop in which I want to send a User Message every 5 seconds. Therefore I wrote a thread which waits for 5 seconds and then sends the Message received by the readLine() Method. If the user doesn't give any input the loop doesn't go on because of the readLine() Method waiting for input. So how can I cancel the readLine() Method?
while (true) {
new Thread() {
#Override
public void run() {
try {
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < 5000) {
}
toClient.println(serverMessage);
clientMessage = fromClient.readLine();
System.out.println(clientName + ": " + clientMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
serverMessage = input.readLine();
}
This looks to be a producer-consumer type problem and I would structure this entirely differently since this fromClient.readLine(); is blocking and thus should be performed within another thread.
So consider reading the user input in another thread into a data structure, a Queue<String> such as a LinkedBlockingQueue<String>, and then retrieve String elements from the queue in the code above every 5 seconds, or nothing if no elements are held in the queue.
Something like....
new Thread(() -> {
while (true) {
try {
blockingQueue.put(input.readLine());
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
try {
while (true) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
String input = blockingQueue.poll();
input = input == null ? "" : input;
toClient.println(input);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
Side notes: don't call .stop() on a thread as that is a dangerous thing to do. Also avoid extending Thread.
I have simple server-client application. There is an option, which client can send to the server, to read generated data.
void getManyFromServer(int numberOfGets){
try{
for(int i=0;i<numberOfGets;i++){
fromServer = sockIn.readLine();
fromServer+="\n";
textArea.append(fromServer);
}
} catch(IOException exc){
/*...*/
}
}
As you can see, I want to read data 10 times, because server will generate 10 different numbers, every 3s:
Random randomGenerator = new Random();
double MEAN = 4.0f;
double VARIANCE = 0.01f;
for(int i=0;i<10;i++){
out.println(Double.toString(MEAN + randomGenerator.nextGaussian()* VARIANCE));
try{
Thread.sleep(3000);
} catch(InterruptedException e){
/*...*/
}
The problem is - clients waits until all "out.println" are finished and then prints everything at once in textArea.
How can I simulate 3s delay between writing data into textArea?
Print out a println from the client, and you'll likely see that it's not reading everything in all at once. Instead, you're likely freezing your GUI by doing this reading on the Swing event thread, and thus preventing it from writing the text to the text component. Solution: use a background thread such as a SwingWorker to do the reading. Please read Lesson: Concurrency in Swing for more on this.
e.g.,
private void getManyFromServer2(final int numberOfGets) {
new SwingWorker<Void, String>() {
#Override
protected Void doInBackground() throws Exception {
try {
for (int i = 0; i < numberOfGets; i++) {
fromServer = sockIn.readLine();
fromServer += "\n";
// textArea.append(fromServer);
publish(fromServer);
}
} catch (IOException exc) {
exc.printStackTrace();
}
return null;
}
#Override
protected void process(List<String> chunks) {
for (String line : chunks) {
textArea.append(line);
}
}
#Override
protected void done() {
try {
get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}.execute();
}
I have a problem with a part of my code. My program have a thread that is getting input from the keyboard and have several threads that are waiting for that input.
The users selects first to what thread he is going to send that input. So lets says that we have 3 threads (0,1,2) plus the thread that gets the keyboard input. The user will select first what thread he wants to interact with and after that he will send the actual data to that thread.
I have a piece of code that is taking care of that process. I use ´LinkedBlockingQueue´ to achieve it.
The keyboard thread puts data in the Queue and the "workers" (the other 3 threads) get that data from that queue.
The problem is that all the threads are listening for that same Queue so I put an ID in that Queue to let the threads know if the data is directed to them or to other thread.
Here is the code:
Thread Thread_OUT = new Thread(new Runnable() {
#SuppressWarnings("unchecked")
#Override
public void run() {
while(true) {
try {
Object recibido= sharedQueue.take();
sharedQueue.put(recibido);
//System.out.println("Im the thread "+ clientID+" and I got "+recibido.toString());
if(Integer.parseInt(recibido.toString())==clientID){ // If it is for me I get the data
String x = CommandShellServer.data.get(clientID); // just get the data (it is in a hashmap)
CommandShellServer.data.clear(); // empty the hashmap
sharedQueue.clear();
OUT = do_something(x);
}
else{ // If it is not I will forward it to other thread
Thread.currentThread().wait(100);
// sharedQueue.put(recibido);
// sharedQueue.clear();
}
As you can see in the code what I do is checking if the thread that is handling the information is the one that is directed to If it is, I process it, and if it is no I put that the data again in the queue to let the other threads to check for it.
If I select the thread 0 to interact with it works. If I select others it doesn't.
Get rid of the shared queue, and let each thread have its own. Then, when you get an input, just dispatch it to the queue of appropriate thread that is intended to receive it.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Application;
import java.util.ArrayList;
import java.util.Scanner;
/**
*
* #author husseyn
*/
public class producteurConsomateur {
static Scanner clavier;
static ArrayList<String> queu;
public static void main(String[] args) {
queu=new ArrayList<>();
new Thread(){
#Override
public void run() {
clavier=new Scanner(System.in);
while (true) {
try {
sleep(1000);
} catch (Exception e) {
}
System.out.print("tape message :");
String nextLine = clavier.nextLine();
queu.add(nextLine);
// notifyAll();
}
}
}.start();
new Thread(){
#Override
public void run() {
while (true) {
try {
try {
wait();
} catch (Exception e) {
}
synchronized(this){
String get = queu.get(0);
String[] messageFormat = get.split(":");
String id=messageFormat[0];
if (id.toLowerCase().equals("id1")) {
String message=messageFormat[0];
queu.remove(0);
System.out.println("message recived to thread ID1 :"+message);
}}
} catch (Exception e) {
}
}
}
}.start();
new Thread(){
#Override
public void run() {
while (true) {
try {
try {
wait();
} catch (Exception e) {
}
synchronized(this){
String get = queu.get(0);
String[] messageFormat = get.split(":");
String id=messageFormat[0];
if (id.toLowerCase().equals("id3")) {
String message=messageFormat[0];
queu.remove(0);
System.out.println("message recived to thread ID3 :"+message);
}}
} catch (Exception e) {
}
}
}
}.start();
new Thread(){
#Override
public void run() {
while (true) {
try {
try {
wait();
} catch (Exception e) {
}
synchronized(this){
String get = queu.get(0);
String[] messageFormat = get.split(":");
String id=messageFormat[0];
if (id.toLowerCase().equals("id2")) {
String message=messageFormat[0];
queu.remove(0);
System.out.println("message recived to thread ID2 :"+message);
}}
} catch (Exception e) {
}
}
}
}.start();
}
}
And here I use a shared queue but you have to respect the message format is like id1:hello or id2:lol
I wanted to know how I can monitor two threads, in such a way that if one thread is in waiting state for a particular time, I would want to run another thread...
To be particular in what I'm doing. I've 2 threads.. Writer Thread :
writer = new Thread() {
public void run() {
try {
Util.copyStream(remoteInput, localOutput);
} catch(IOException e) {
e.printStackTrace();
System.exit(1);
}
}
};
writer.setPriority(Thread.currentThread().getPriority() + 1);
writer.start();
reader.setDaemon(true);
reader.start();
try {
writer.join();
reader.interrupt();
} catch(InterruptedException e) {
}
and the reader thread :
reader = new Thread() {
public void run() {
int ch;
try {
while(!interrupted() && (ch = localInput.read()) != -1) {
System.out.print((char)ch);
localOutput.write(ch);
if (ch==10) {
remoteOutput.write(ch);
remoteOutput.flush();
sleep(1000);
continue;
}
remoteOutput.write(ch);
remoteOutput.flush();
}
} catch(Exception e) {
e.printStackTrace();
}
}
};
So, if my writer thread is not writing from "remoteInput" to "localOutput" for more than a particular time for example 3 secs, I should be "run"ing the reader thread.. ,so that reader reads from "localInput" and writing to "remoteOutput".
localInput and remoteInput are InputStreams, whereas, remoteInput and remoteOutput are simple OutputStreams. I also wanted to know if it's possible to do this using java.util.Timer
Please help me through..
Thanks in advance.
You can use combination of wait/notify along with Timer class to decide when to trigger notify events.
Here is a simplified version of my application showing what I'm doing.
/*
in my app's main():
Runner run = new Runner();
run.dowork();
*/
class Runner
{
private int totalWorkers = 2;
private int workersDone = 0;
public synchronized void workerDone()
{
workersDone++;
notifyAll();
}
public synchronized void dowork()
{
workersDone = 0;
//<code for opening a file here, other setup here, etc>
Worker a = new Worker(this);
Worker b = new Worker(this);
while ((line = reader.readLine()) != null)
{
//<a large amount of processing on 'line'>
a.setData(line);
b.setData(line);
while (workersDone < totalWorkers)
{
wait();
}
}
}
}
class Worker implements Runnable
{
private Runner runner;
private String data;
public Worker(Runner r)
{
this.runner = r;
Thread t = new Thread(this);
t.start();
}
public synchronized void setData(String s)
{
this.data = s;
notifyAll();
}
public void run
{
while (true)
{
synchronized(this)
{
wait();
//<do work with this.data here>
this.runner.workerDone();
}
}
}
}
The basic concept here is that I have a bunch of workers which all do some processing on an incoming line of data, all independently, and write out the data wherever they like - they do not need to report any data back to the main thread or share data with each other.
The problem that I'm having is that this code deadlocks. I'm reading a file of over 1 million lines and I'm lucky to get 100 lines into it before my app stops responding.
The workers, in reality, all do differing amounts of work so I want to wait until they all complete before moving to the next line.
I cannot let the workers process at different speeds and queue the data internally because the files I am processing are too large for this and won't fit in memory.
I cannot give each worker its own FileReader to independently get 'line', because I do a ton of processing on the line before the workers see it, and do not want to have to re-do the processing in each worker.
I know I'm missing some fairly simple aspect of synchronization in Java but I'm stuck at this point. If someone could explain what I'm doing wrong here I would appreciate it. I believe I'm misunderstanding some aspect of the synchronization but I'm out of ideas for attempting to fix it.
Working directly with synchronized, wait(), and notify() is definitely tricky.
Fortunately the Java Concurrency API provides some excellent control objects for this sort of thing that are much more intuitive. In particular, look at CyclicBarrier and CountDownLatch; one of them almost certainly will be what you're looking for.
You may also find a ThreadPoolExecutor to be handy for this situation.
Here's a simple example / conversion of your snippet that produces the following output (without deadlock, of course):
Read line: Line 1
Waiting for work to be complete on line: Line 1
Working on line: Line 1
Working on line: Line 1
Read line: Line 2
Waiting for work to be complete on line: Line 2
Working on line: Line 2
Working on line: Line 2
Read line: Line 3
Waiting for work to be complete on line: Line 3
Working on line: Line 3
Working on line: Line 3
All work complete!
public class Runner
{
public static void main(String args[]) {
Runner r = new Runner();
try {
r.dowork();
} catch (IOException e) {
// handle
e.printStackTrace();
}
}
CyclicBarrier barrier;
ExecutorService executor;
private int totalWorkers = 2;
public Runner() {
this.barrier = new CyclicBarrier(this.totalWorkers + 1);
this.executor = Executors.newFixedThreadPool(this.totalWorkers);
}
public synchronized void dowork() throws IOException
{
//<code for opening a file here, other setup here, etc>
//BufferedReader reader = null;
//String line;
final Worker worker = new Worker();
for(String line : new String[]{"Line 1", "Line 2", "Line 3"})
//while ((line = reader.readLine()) != null)
{
System.out.println("Read line: " + line);
//<a large amount of processing on 'line'>
for(int c = 0; c < this.totalWorkers; c++) {
final String curLine = line;
this.executor.submit(new Runnable() {
public void run() {
worker.doWork(curLine);
}
});
}
try {
System.out.println("Waiting for work to be complete on line: " + line);
this.barrier.await();
} catch (InterruptedException e) {
// handle
e.printStackTrace();
} catch (BrokenBarrierException e) {
// handle
e.printStackTrace();
}
}
System.out.println("All work complete!");
}
class Worker
{
public void doWork(String line)
{
//<do work with this.data here>
System.out.println("Working on line: " + line);
try {
Runner.this.barrier.await();
} catch (InterruptedException e) {
// handle
e.printStackTrace();
} catch (BrokenBarrierException e) {
// handle
e.printStackTrace();
}
}
}
}
IMHO you have improperly placed "workersDone = 0".
public synchronized void dowork()
{
// workersDone = 0;
//<code for opening a file here, other setup here, etc>
Worker a = new Worker(this);
Worker b = new Worker(this);
while ((line = reader.readLine()) != null)
{
workersDone = 0;
//<a large amount of processing on 'line'>
a.setData(line);
b.setData(line);
while (workersDone < totalWorkers)
{
wait();
}
}
}