Cannot reset StringBuffer in JavaFX Application - java

I am working on a college course project, a JavaFX application that is simulating a garage with vehicles moving around. Following on this answer, I created a mechanism for constantnly refreshing GUI without flooding the JavaFX thread.
The entire code can be found here.
Observer is a daemon thread whose task is computing a String value for output and sending it it to a TextArea, which is constantly being updated.
Observer run method:
#Override
public void run() {
while (true) {
synchronized (Garage.getLock()) {
try {
// buffer = new StringBuffer("");
buffer.append('\n');
garage.print(buffer);
buffer.append('\n');
garage.outputText.set(buffer.toString());
System.out.println(buffer.toString());
Garage.getLock().wait(3000);
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
Garage.getLock().notifyAll();
}
}
}
}
Observer object has a reference to the model class - garage. print() method of the Garage class basically appends stuff to the buffer.
The complete output is printed to the console, which works fine. The output is also used to set outputText, a SimpleStringProperty, which has a listener attached in the MainControllerClass.
outputText member:
public class Garage implements Externalizable {
...
public SimpleStringProperty outputText = new SimpleStringProperty();
...
}
Refreshing the GUI is initiated with a button click.
MainController class:
package garage.controller;
import java.util.concurrent.atomic.AtomicInteger;
import garage.model.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
public class MainController {
#FXML
private TextArea output;
#FXML
private Button startButton;
private Garage model;
public MainController() {
}
private AtomicInteger control = new AtomicInteger(-1);
#FXML
public void initialize() {
}
#FXML
private void handleStartButton() {
model.outputText.addListener(new ChangeListener<String>() {
#Override
public void changed(final ObservableValue<? extends String> observable, final String oldValue,
final String newValue) {
if (control.getAndSet(1) == -1) {
javafx.application.Platform.runLater(new Runnable() {
#Override
public void run() {
control.set(-1);
output.setText(newValue);
}
});
}
}
});
}
public void setModel(Garage model) {
this.model = model;
}
}
When I run the application and click the button, everything is going well. TextArea is updated in real time. Since the output is constantly being appended to the StringBuffer, I wanted to refresh it in every cycle and get something like a simulation.
This is where the problems start.
When I uncomment the line in the Observer run method
// buffer = new StringBuffer("");
nothing is being printed to the TextArea. The console output is working well.
I also tried with other StringBuffer methods like delete and setLenght but nothing seems to work. However I try to clean the buffer, TextArea is no longer updated.
I cannot seem to reset the StringBuffer.
What am I missing here?
EDIT: print() methods
Garage print method
public void print(StringBuffer buffer) {
synchronized (Garage.lock) {
synchronized (lock) {
for (int i = 0; i < platformCount; i++)
platforms.get(i).print(buffer);
}
}
}
GarageItem print method
package garage.model;
import java.io.*;
public interface GarageItem extends Serializable {
public void print(StringBuffer buffer);
}
Lane print method
package garage.model;
public class Lane implements GarageItem {
private static final long serialVersionUID = 5L;
#Override
public void print(StringBuffer buffer) {
synchronized (Garage.getLock()) {
buffer.append('.');
}
}
}
ParkingSpot print method
package garage.model;
public class ParkingSpot implements GarageItem {
private static final long serialVersionUID = 4L;
#Override
public void print(StringBuffer buffer) {
synchronized (Garage.getLock()) {
buffer.append('*');
}
}
}
Vehicle print method
#Override
public void print(StringBuffer buffer) {
synchronized (Garage.getLock()) {
buffer.append(symbol);
}
}
where symbol is 'V'.

Found the answer today. My text example was trivial and by the time I clicked the handleStartButton, all of the cars have finished moving and parked in the garage.
Because I reset the buffer in every loop iteration, it meant that the state of the garage didn't change anymore and it's String representation was the same. Because of this, change listener was not triggered and nothing was printed out to the TextArea.

Related

Multithreading in java cannot communicate change

I have to change a Boolean variable in application thread(setReadyToUpload) and hearing this change(isReadyToUpload) another thread (server thread) will do something.Though server thread is in a while loop and checking all he time it is not catching the change when i change the Boolean variable in application thread.
Application thread
package server;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.stage.FileChooser;
import java.io.File;
public class serverController {
serverMain main;
#FXML
private Button upload;
#FXML
private ProgressIndicator indicator;
#FXML
void pressed(ActionEvent event) {
FileChooser fc=new FileChooser();
File file=fc.showOpenDialog(main.getStage());
if(file!=null) {
main.setFileLoaction(file.getAbsolutePath());
System.out.println("it is done");
main.setReadyToUpload(true);
}
else
{
Alert alert=new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Upload problem");
alert.setContentText("You have'nt select any file to upload");
alert.showAndWait();
}
}
public void setMain(serverMain main) {
this.main = main;
}
}
server thread
package tcpobject;
import java.io.File;
import java.util.*;
import server.serverMain;
import util.NetworkUtil;
public class WriteThreadServer implements Runnable {
private Thread thr;
private NetworkUtil nc;
private serverMain main;
private LargeFile o;
private LargeFileInserter lfi;
String name;
public WriteThreadServer(NetworkUtil nc,String name, serverMain main) {
this.nc = nc;
this.name=name;
this.thr = new Thread(this);
this.main=main;
thr.start();
}
public void run() {
while(true)
{
try {
//System.out.println("it is "+main.isReadyToUpload());
// if i print this then thelower block works good but if i dont it cant catch the change
System.out.println("it is checking");
if(main.isReadyToUpload())
{
System.out.println("it is ru");
FileDataHandler();
}
if(main.isStartUpload()) {
//System.out.println("it is su");
LargeFileHandler();
System.out.println("it is su");
for (int i = 0; lfi.hasMoreBytes(); i++) {
o = lfi.nextByte();
nc.write(o);
}
lfi.close();
}
} catch(Exception e) {
System.out.println (e+" here");
e.printStackTrace();
nc.closeConnection();
}
}
}
void FileDataHandler ()
{
FileDataMessage fd=new FileDataMessage(main.getFileLoaction());
nc.write(fd);
main.setReadyToUpload(false);
}
void LargeFileHandler ()
{
try {
lfi=new LargeFileInserter(main.getFileLoaction());
} catch (Exception e) {
e.printStackTrace();
}
//FileDataMessage fd=new FileDataMessage("F:\\L-2 T-1\\EEE 263\\Electronic devices and ckt theory- boylestad 11th edition.pdf");
//System.out.println(fd);
//System.out.println(fd.sizetoPrint());
LargeFile o;
main.setStartUpload(false);
}
}
All the function and variable is written in main class and both thread have access to that class.
Without having the rest of the code available, methods setReadyToUpload and isReadyToUpload have issues with visibility of shared object, which is flag you are setting to true.
What could happen is that two threads run on different cores, and one thread updates the flag to true. This update could happen within CPU cache which is not readable by the another thread checking for the value as long the change is not flushed back into main memory.
You could fix current design by :
a) having the flag volatile which will force updates of cache lines between CPU registers
b) make methods synchronized, with the same effect as above
What you should do instead however, would be to use wait and notify instead of busy waiting in the server thread and wasting the CPU cycles.
Simply create monitor variable such as:
private final Object monitor = new Object();
and in the server code do:
synchronized(monitor) {
monitor.wait():
}
so when the change is ready you could notify change from another thread like this:
synchronized(monitor)
{
monitor.notify();
}
Server could implement Observer while your client is Subject. This would let you simply notify the changes via Observer's interface method update.
Note that in theory wait could be interrupted, and therefore you should check if the condition is met upon wake up, and if not continue waiting.

Create a new Event Handler and Source

I have a User Interface(UI) class. It creates some thread (lets call it T) to do some work. I want my UI class to be notified when T is done working.
I think I need to create an event handler in UI class (among onClick() etc) and trigger it from T.
Question: Is this possible ? How ?
//to be clear, UI class does already have some event Handlers which are triggered by functions I didn't write. like onClick() , etc.
This is a fairly common requirement as you generally want to be doing as little as possible on the UI thread.
If you are using swing, have a look at the SwingWorker class. If you are not using swing, you might want to have a look at ExecutorService and FutureTask.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class Futures {
public static void main(String[] args) {
UI ui = new UI();
FutureHandle<String> handle = new FutureHandle<String>(new BigJob());
FutureHandle<String> handle2 = new FutureHandle<String>(new BigJob());
ui.doUIStuff("Things can happen on the UI thread");
ui.startHeavyLiftingJob(handle);
ui.doUIStuff("I've got a big job running, but I'm still responsive");
ui.startHeavyLiftingJob(handle2);
}
/**
* Your UI class. Don't want to do anything big
* on the UI's thread.
*/
static class UI implements Listener<String> {
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
public void doUIStuff(String msg) {
System.out.println(msg);
}
public void startHeavyLiftingJob(FutureHandle<String> handle) {
System.out.println("Starting background task");
handle.setListener(this);
threadPool.execute(handle);
}
public void callback(String result) {
System.out.println("Ooh, result ready: " + result);
}
}
/**
* A handle on a future which makes a callback to a listener
* when the callable task is done.
*/
static class FutureHandle<V> extends FutureTask<V> {
private Listener<V> listener;
public FutureHandle(Callable<V> callable) {
super(callable);
}
#Override
protected void done() {
try {
listener.callback(get());
} catch (InterruptedException e) {
//handle execution getting interrupted
} catch (ExecutionException e) {
//handle error in execution
}
}
public void setListener(Listener<V> listener) {
this.listener = listener;
}
}
/**
* Class that represents something you don't want to do on the UI thread.
*/
static class BigJob implements Callable<String> {
public String call() throws Exception {
Thread.sleep(2000);
return "big job has finished";
}
}
interface Listener<V> {
public void callback(V result);
}
}

java remote function need calling twice

I've created a java code (swing GUI JFrame form) that call another class function (which is in another project) when the button is pressed, but it needs me to click the button twice in order to successfully return the value from the called function. Is there any solution?
here is my code,
The GUI
package aarib;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import AlKhalil.ui.Aarib;
public class GUI extends javax.swing.JFrame {
public String Input;
public String Lexems;
public Aarib A;
public GUI() {
initComponents();
A = new Aarib();
jTextField1.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
jLabel2.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if(jTextField1.getText().isEmpty())
{
jLabel2.setText("No input");
}
else{
Input = jTextField1.getText().toString();
A.inputText= Input;
try {
Lexems = A.LexicalAnalysis();
jLabel2.setText(Lexems);
} catch (Exception ex) {
jLabel2.setText("Error");
Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
and the remote function
package AlKhalil.ui;
import java.util.*;
import java.util.List;
import AlKhalil.token.*;
import AlKhalil.analyse.*;
import AlKhalil.*;
import AlKhalil.result.*;
public class Aarib {
public Analyzer analyzer;
public String myResult="";
public String inputText="";
public Aarib() {
Settings settings = new Settings();
analyzer = new Analyzer();
}
public String LexicalAnalysis() throws Exception {
Thread t = new Thread()
{
public void run()
{
//some code
...
...
...
}
};
t.start();
return myResult;
}
}
Thanks in advance :)
The solution is to wait for the result produced in the Thread t. With your current code you start a concurrent thread and instantly return the attribute myResult. With the second click on your button the myResult is (most times) filled by the thread and returned after starting another concurrent thread doing the calculation.
I suggest considering some kind of Observer-Pattern for your program. Your GUI then should obsever the calculating thread and get notified about a result, which then will be handled.
But as we all cannot see the code executed in the thread and as you wait for the thread to finish, why not simply not use a thread.

I can't figure out what is wrong with this threads, I am trying to understand multithreading

I am sorry that this is too long, and it may seem as too much asking, but If you can figure out what is wrong at a glance, please let me know.
In this program I try to input some words (phrase) from the keyboard every time taking one token and assign it to an object sharedStorer (then print the assigned value to keep track of what is input as I have a chain of words to input separately). This is done by one thread (Thread of class Retriever which implements Runnable)
There is another thread of class TokenReader that reads the value of sharedStorer and print it out. TokenReader waits for Retriever for input and when Retriever tries to input while TokenReader has not yet read the previous token Retriever waits.
The question I have is that at the end TokenReader waits forever for Retriever which has completed its task, and so the program never terminates.
Here is all 4 classes (and 1 Interface) I am using to perform the desired task.
package Multithreads;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExerciseTest {
public static void main(String[] args) {
ExecutorService app=Executors.newFixedThreadPool(2);
Storer st=new SyncStorer();
System.out.println("Operation performed\t\t Value");
try{
app.execute(new Retriever(st));
app.execute(new TokenReader(st));
}catch(Exception e){
e.printStackTrace();
}
app.shutdown();
}
}
package Multithreads;
public interface Storer {
public void set(String token);
public String get();
}
package Multithreads;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Retriever implements Runnable {
private Scanner scanner;
private String token;
private String currentToken;
private Storer sharedStorer;
private Random rd=new Random();
public int tokenLength=0;
public Retriever(Storer st) {
sharedStorer=st;
}
public Retriever() {
}
#Override
public void run() {
System.out.println("Enter a phrase");
scanner = new Scanner(System.in);
token=scanner.nextLine();
StringTokenizer tokenizer=new StringTokenizer(token);
while(tokenizer.hasMoreTokens())
{
tokenLength++;
currentToken=tokenizer.nextToken();
try{
Thread.sleep(10*rd.nextInt(2000));
sharedStorer.set(currentToken);
}catch(NoSuchElementException e){
e.printStackTrace();
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("Done Inputting The phrase");
}
}
package Multithreads;
import java.util.Random;
public class TokenReader implements Runnable {
private Random rd=new Random();
private Storer sharedStorer;
Retriever rtr=new Retriever();
private int count=rtr.tokenLength;
public TokenReader(Storer st) {
sharedStorer=st;
}
#Override
public void run() {
String str="null";
int i=0;
try {
while(i <= count){
Thread.sleep(15*rd.nextInt(2000));
str=sharedStorer.get();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer done reading");
}
}
package Multithreads;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SyncStorer implements Storer {
private Lock accessLock=new ReentrantLock();
private Condition canInput = accessLock.newCondition();
private Condition canRead = accessLock.newCondition();
private String string="null";
private boolean isEmpty=false;
#Override
public void set(String token) {
accessLock.lock();
try
{
while(isEmpty){
System.out.println("Retriever waiting");
canInput.await();
}
string=token;
isEmpty=true;
System.out.println("Retriever inputs\t\t "+string);
canRead.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
accessLock.unlock();
}
}
#Override
public String get() {
accessLock.lock();
try{
while(!isEmpty)
{
System.out.println("No token to read");
canRead.await();
}
isEmpty=false;
System.out.println("TokenReader reads\t\t "+string);
canInput.signal();
}catch(InterruptedException e)
{
e.printStackTrace();
}finally{
accessLock.unlock();
}
return string;
}
}
The problem that is causing the app to run forever is that this is an infinite loop:
while(i <= count){
Thread.sleep(15*rd.nextInt(2000));
str=sharedStorer.get();
}
because you are not decrementing i. And the interrupt-based mechanism you are trying to use to break out of the loop (via an exception!) is broken too.
The Thread.sleep(15*rd.nextInt(2000)) line looks like a hack so that you can get an InterruptedException when the task is interrupted, but:
the point of sleeping for a random number of milliseconds escapes me, and
it would be simpler to just call Thread.interrupted().
Besides, the approach isn't reliable anyway because there is a chance that the interrupt will happen after the point at which you are waiting / testing for it; i.e. in the get() call. And if that get() call is never going to return because the store is empty and the retriever has ended ... then you will wait "for ever".
There is one final problem. You need to call app.shutdownNow() if you want the executor service to interrupt the worker threads ...
If I was trying to implement this (using interrupts), I'd change it so that get and set didn't "gobble up" the interrupt. If they see the interrupt, they should either:
allow the InterruptedException to propagate (after relevant cleanup), or
set the thread's interrupted flag again in the exception handler.

Message passing to asynchronus working thread in Java J2ME

I'm working on a J2ME Bluetooth application, and one of the classes searches for other Bluetooth devices. It does this in another thread, so the GUI doesn't freeze up.
The problem I have is how to pass messages to the thread. I can ask it to search, or cancel searching, and it can tell the GUI it has found some other devices. Currently I use notify and wait, but that seems like a hack. What I really want is some way of calling notify with a parameter, for example what I want it to do. Is there any way to do this?
The general approach to this kind of situation must be as follows:
Decouple the remote source of the data with the "View".
Make sure that the view is capable of updating dynamically when the underlying data changes. J2ME components do this by default - but if you author your own components, then you must take this into consideration.
Run a separate thread and retrieve data.
Notify the view whenever the data arrives.
The working code for the MIDlet is posted below
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.*;
public class AsyncUI extends MIDlet implements SearchListener, CommandListener{
Command CANCEL = new Command("STOP SEARCH",Command.CANCEL,1);
Command EXIT = new Command("EXIT",Command.EXIT,2);
SearchDevices finder = new SearchDevices();
List deviceList = new List("List of Devices",List.IMPLICIT);
public void startApp() {
Display d = Display.getDisplay(this);
finder.setSearchListener(this);
deviceList.addCommand(CANCEL);
deviceList.addCommand(EXIT);
deviceList.setCommandListener(this);
d.setCurrent(deviceList);
new Thread( finder).start();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void found( Device d){
deviceList.append(d.getName(), null);
}
public void commandAction( Command c, Displayable d){
if( c == CANCEL){
finder.cancel();
deviceList.removeCommand(CANCEL);
}else if( c== EXIT ){
finder.cancel(); /* Cleanup all resources before you quit*/
notifyDestroyed();
}
}
}
class SearchDevices implements Runnable{
private boolean keepFinding=true;
private static final int LONG_TIME=10000; /* 10 Seconds */
SearchListener l =null; /* Currently only one listener. There could be many*/
public void run(){
int i =0;
System.out.println(" -- Started the activity of finding --");
while( keepFinding){
try {
Thread.currentThread().sleep(LONG_TIME);
Device d = new Device("Device Found "+i);
i++;
System.out.println(" -- Found the device --");
l.found(d);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println(" -- No more devices will be found --");
}
public void cancel(){ keepFinding = false; }
public void setSearchListener( SearchListener l){this.l=l;}
}
class Device{
String name;
public Device(String name ){ this.name = name; }
public String getName(){ return name ; }
}
interface SearchListener{
public void found( Device device);
}
You'll have to implement you're own blocking queue, this is actually a producer-consumer problem. Once you have a blocking queue, you can then easily wrap pushes to the queue in their own methods, making it feel like you're doing asynchronous calls to the worker thread.

Categories