Java socket BufferedReader reads all inputs from loop at once - java

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();
}

Related

How to handle third-party Java code in a Task submitted to ExecutorService in case it has an infinite loop

Let's say I have a third-party Java library called in a Task submitted to ExecutorService.
I trust the third-party library to not be malicious, but there is a rare chance that there are programming errors that can cause it to get stuck in an infinite loop, and if this is the case, I cannot fix it to address those rare occasions.
What is the best way to handle this so that the application doesn't get stuck as well? Is shutdownNow() good enough to handle this situation?
There's a related issue Stop an infinite loop in an ExecutorService task but this relies on the ability of the programmer to be cooperative and detect Thread.currentThread().isInterrupted() to stop processing, which I can't rely on.
(In my case it's Jython code; in an early version of Jython the interpreter apparently didn't check Thread.currentThread().isInterrupted(), not sure what it does now... but my question is general for any 3rd-party Java code.)
If the task has an infinite loop that does not check for the thread interrupted status and does not use methods that throw InterruptedExceptions, it won't be stopped by shutdownNow().
Simple example that doesn't allow you program to finish:
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(1);
e.submit(() -> { while (true); });
e.shutdownNow();
System.out.println("Main is finished but the app keeps running");
}
One way would be to run the thread as a daemon:
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(1, r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
});
e.submit(() -> { while (true); });
e.shutdownNow();
System.out.println("Main is finished and the app can exit");
}
Following my correct reading of the question I put together this set of classes. Relatively simple: One Runnable that connects to a socket sending input and retrieving output from a secondary jvm that invokes the erratic library.
If after 3 tries no response has been received the secondary jvm is killed. But it could be relaunched. The secondary jvm has an exit hook to close down sockets.
class SafetyValve implements Runnable{
PrintWriter out;
BufferedReader in;
Socket s = null;
AtomicBoolean flag;
SafetyValve(AtomicBoolean b){
flag = b;
}
#Override
public void run() {
try {
s = new Socket("localhost", 9000);
out = new PrintWriter(s.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
while (!Thread.currentThread().isInterrupted()){
flag.set(false);
out.print(0);
out.flush();
System.out.print(in.read());
flag.set(true);
}
} catch (Exception e) {
e.printStackTrace();
}
finally{
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Main/Controller class. It uses a Thread class for control
public class Switch {
public static void main(String[] args) {
try {
AtomicBoolean flag = new AtomicBoolean(false);
int counter = 0;
ProcessBuilder pb = ...
pb.directory(,,,);
Process p = pb.start();
SafetyValve sv = new SafetyValve(flag);
Thread t = new Thread(sv);
t.start();
while(t.getState() != Thread.State.RUNNABLE){
Thread.sleep(10);
}
while(true){
if (flag.get() == false){
if (++counter == 3){
while(t.getState() != Thread.State.TERMINATED){
p.destroyForcibly();
t.interrupt();
Thread.sleep(10);
}
break;
}
}
else
counter = 0;
Thread.sleep(100);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The secondary jvm has an standard server socket implementation:
class UnYielding{
int i = 0;
int returnInt(){
i++;
if (i > 2)
while(true);
return i;
}
}
class Hook extends Thread{
RunWild rw;
Hook(RunWild wr){
rw = wr;
}
public void run() {
try {
System.out.println("exit...");
System.out.flush();
rw.socket.close();
rw.server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class RunWild {
ServerSocket server;
Socket socket;
RunWild(){
Runtime.getRuntime().addShutdownHook(new Hook(this));
}
public static void main(String[] args){
UnYielding u;
int i;
PrintWriter out;
BufferedReader in;
RunWild rw = new RunWild();
try {
rw.server = new ServerSocket(9000);
rw.socket = rw.server.accept();
out = new PrintWriter(rw.socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(rw.socket.getInputStream()));
u = new UnYielding();
while ((i = in.read()) != -1){
out.print(u.returnInt());
out.flush();
Thread.sleep(10);
System.out.print("waiting...");
System.out.flush();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I have tested this against 1.8 on OS X it works as expected. If this unstable classes are needed this is one way of doing it

Feeding several threads with data using Java

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

Java Thread drives CPU to 100%

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);
}
});
}

In Android, I need to get data via TCP in an onDraw() method

As the title describes, I have a View class in which I need to reach out to get some data via TCP before I update the drawing. When I implemented this in my usual new Thread()...start() construction Eclipse whined at me about instantiating something new in an onDraw() method. In response to that, I reconfigured my thread as a class variable and I'm attempt to execute t.start() in the onDraw() loop.
However, there must be some thread baby-sitting I'm not aware about because my code is throwing an exception (java.lang.IllegalThreadStateException: Thread already started) when it attempts to start the thread the second time. The following is the current version of my code:
Thread t = new Thread()
{
public void run()
{
try
{
String st1 = getNetwork(); // Get network information
if (null != st1)
{
String[] st = st1.substring (st1.indexOf (' ') + 1, st1.length()).split (",+");
setNeighbors (st.length);
for (String s:st)
{
Log.e (TAG, s.trim());
String[] t1 = s.trim().split ("\\s+");
numbers.add (t1[0]);
addresses.add (t1[1]);
states.add (t1[2]);
}
}
}
catch (Exception ex)
{ }
finally
{
NetworkView.this.wait = false;
}
}
};
#Override
protected void onDraw (final Canvas canvas)
{
if (++drawCtr % 300 == 0)
{
this.wait = true;
t.start();
while (wait);
try
{
t.join();
}
catch (InterruptedException e) { }
}
update (canvas);
try { Thread.sleep (50); }
catch (InterruptedException e) { }
invalidate();
}
I get that the 2nd time around, my thread has already been started. How do I "reset" or "unstart" it for a 2nd attempt??
As Henry pointed out, my initial concept was a bad idea. A much more workable architecture was to have the TCP thread control the redraw, rather than having the redraw thread control the TCP data exchange, especially because there's no need (at least in my case) to redraw the screen between TCP updates. Hence, I implemented this thread in my View object's constructor:
(new Thread()
{
public void run()
{
while (looping)
{
try
{
// Get the important data via TCP (CAN'T be on the UI thread)
String st1 = tcpClient.getNetwork();
String st2 = tcpClient.getDiscovery();
}
catch (Exception ex)
{ }
finally
{
try
{
// Redraw the display (HAS TO be on the UI thread)
net.runOnUiThread (new Runnable()
{
#Override
public void run()
{
invalidate();
}
});
}
catch (Exception ex)
{ }
try { Thread.sleep (2000); }
catch (InterruptedException e) { }
}
}
}
}).start();
The key is the invalidate() call in the finally block (that needs to be run on the UI thread). That will update the screen based on the fresh new information.

Proper synchronization of Java threads using wait/notifyAll?

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();
}
}
}

Categories

Resources