I was reading the documentation for the class Task
final Task<Void> task = new Task<Void>() {
#Override public Void call() {
for(int i=0;i<datesAndStudies.length;i++){
updateProgress(i,datesAndStudies.length);
DoSomething something = new DoSomething();
something.VeryLongAndTimeConsumingMethod(i);
}
return null;
}
};
And I notice that updateProgress is protected and workdone/totalwork are both defined as public final ReadOnlyDoubleProperty.
Is there a way/workaround to update/call updateProgress or edit those values(workdone/totalwork) from the method: VeryLongAndTimeConsumingMethod(int i) in the class DoSomething ?
Even if updateProgress(...) were public, you'd have to pass a reference to the Task to your DoSomething class, which creates some really ugly coupling. If you have that level of coupling between your Task implementation and your DoSomething class, you may as well just define the long, time consuming method in the Task subclass itself, and get rid of the other class:
final Task<Void> task = new Task<Void>() {
#Override
public Void call() {
for (int i=0; i<datesAndStudies.length; i++) {
veryLongAndTimeConsumingMethod(i);
}
return null ;
}
private void veryLongAndTimeConsumingMethod(int i) {
// do whatever...
updateProgress(...);
}
};
To preserve your decoupling, just define a DoubleProperty representing the progress in DoSomething, and observe it from the Task, calling updateProgress(...) when it changes:
public class DoSomething {
private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper(this, "progress");
public double getProgress() {
return progress.get();
}
public ReadOnlyDoubleProperty progressProperty() {
return progress.getReadOnlyProperty();
}
public void veryLongAndTimeConsumingMethod(int i) {
// ..
progress.set(...);
}
}
Then:
final Task<Void> task = new Task<>() {
#Override
public Void call() {
for (int i=0; i<datesAndStudies.length; i++) {
DoSomething something = new DoSomething();
something.progressProperty().addListener(
(obs, oldProgress, newProgress) -> updateProgress(...));
something.veryLongAndTimeConsumingMethod();
}
}
}
Related
I have a JavaFX service in which Task is created to do some work:
public class MyService extends Service<Void> {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
// do some work
return null;
}
};
}
}
I also have a handler for success:
myService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle( final WorkerStateEvent event ) {
// check what Task has finished
}
});
As it is possible to run the service more than once concurrently, I wan't to be able to distinguish from success handler what instance of Task has finished. Looking into the doc, I could not find any way, how to do it.
My idea was to extend Task to contain some id, e.g. integer, and then to be able obtain that instance from event handler.
Any idea, how to achieve such behavior would be much welcome.
Thanks in advance.
First, I would question why you needed to do this. The task itself should encapsulate all the logic that is specific to its own particular instance. It feels like there should be a better solution to whatever it is you're trying to achieve.
So the most obvious way to do this would be to have your Task return the value you are interested in. E.g.
public class MyService extends Service<Integer> {
private int nextId = 0 ;
#Override
protected Task<Integer> createTask() {
private final int id = ++nextId ;
return new Task<Integer>() {
#Override
protected Integer call() throws Exception {
// do some work
return id;
}
};
}
}
Then
Service<Integer> service = new MyService();
service.setOnSucceeded(e -> System.out.println("Task " + service.getValue() + " finished"));
Note also that you can override the succeeded() method of Task (as well as registering a handler with the service). So you can do
public class MyService extends Service<Void> {
private int nextId = 0;
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
final int id = ++nextId ;
#Override
protected Void call() throws Exception {
// do some work
return null;
}
#Override
protected void succeeded() {
super.succeeded();
System.out.println("Task "+id+" completed successfully");
}
};
}
}
The succeeded() method is invoked on the FX Application Thread.
If you really want to manage this via the service, you could just keep a reference to the latest task that was started in the service implementation. Since a Service can only run one task at a time, when the service enters the SUCCEEDED state, this is guaranteed to be the task that just completed. For example:
public class MyService extends Service<Void> {
private Task<Void> mostRecentTask ;
#Override
protected Task<Void> createTask() {
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
// do some work
return null;
}
};
task.setOnRunning(e -> mostRecentTask = task);
return task ;
}
public Task<Void> getMostRecentTask() {
return mostRecentTask ;
}
}
Then
MyService service = new MyService();
service.setOnSucceeded(e -> {
Task<Void> completedTask = service.getMostRecentTask();
// ...
});
But, as I said before, it feels like there should be a more elegant way to achieve whatever it is you're trying to do at a more fundamental level.
I'm trying make a reactive application that listens to a network socket on a separate thread for prices and got a bit stumped with how exactly to construct the Observable. Much of the interfaces I have are constrained by the API I am using and therefore cannot change. I distilled what I am trying to do as a test below, but I can't see how to fill in the body of the getPriceReactive() method such that the prices are printed on the console by the subscriber (see the comment in the code).
public class PriceObservableTest {
// This interface is defined externally and used by the API
private interface ITickHandler {
void priceReceived(double price);
}
// Stores the price (currently just one double for illustration)
private class Tick {
double price = Double.NaN;
}
// Implementation of handler called by API when it receives a price
private class TickHandler implements ITickHandler {
private final Tick tick;
TickHandler() { this.tick = new Tick(); }
#Override public void priceReceived(double x) { tick.price = x; }
}
// This class emulates the API delivering prices from the socket
private class PriceSource {
private final Thread thread;
PriceSource(final ITickHandler handler) {
thread = new Thread(new Runnable() {
final Random r = new Random();
#Override public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
handler.priceReceived(r.nextDouble() * 100);
} catch (InterruptedException e) {
break;
}
}
System.out.println("Price thread closed");
}
});
}
void subscribe() { thread.start(); }
void unsubscribe() { thread.interrupt(); }
}
#Test
public void simpleTest() throws Exception {
final ITickHandler handler = new TickHandler();
// Simulate some prices received periodically from a socket
PriceSource prices = new PriceSource(handler);
Observable<Tick> reactive = getPriceReactive(handler);
reactive.subscribe(new Subscriber<Tick>() {
#Override public void onCompleted() { }
#Override public void onError(Throwable e) { }
#Override public void onNext(Tick tick) {
System.out.println("Received price: " + tick.price);
}});
// Observe prices for 1 second. The subscriber should print them to console
prices.subscribe();
Thread.sleep(1000);
prices.unsubscribe();
}
// Returns an observable that reacts to price changes
private Observable<Tick> getPriceReactive(ITickHandler handler) {
return Observable.create(new Observable.OnSubscribe<Tick>() {
#Override public void call(Subscriber<? super Tick> subscriber) {
// How to call subscriber.onNext() whenever
// priceReceived() is called with a new price?
}
});
}
}
Somehow subscriber.onNext() needs to be called whenever the API calls priceReceived(), but I can't quite see how to achieve this. Of course I could store a reference to the subscriber in the TickHandler but this kind of defeats the purpose of having an Observable, doesn't it?
Transition to Observable in ITickHandler implementation. You are not controlling the subscriber(s) but the publisher
private class TickHandler implements ITickHandler {
private final Tick tick;
private final PublishSubject<Tick> priceSubject;
TickHandler() {
this.tick = new Tick();
this.priceSubject = PublishSubject.create();
}
#Override public void priceReceived(double x)
{
tick.price = x;
priceSubject.onNext(tick);
}
public Observable<Tick> priceReceivedObservable()
{
return priceSubject.asObservable();
}
}
And you can use it in your tests like:
final ITickHandler handler = new TickHandler();
PriceSource prices = new PriceSource(handler);
handler.priceReceivedObservable()
.subscribe(new Subscriber<Tick>() {
#Override public void onCompleted() { }
#Override public void onError(Throwable e) { }
#Override public void onNext(Tick tick) {
System.out.println("Received price: " + tick.price);
}});
I warn you, it's not tested since I don't do a lot of Java :)
I have a class OuterClass that contains a List and there is a thread ListWorker that is started in OuterClass that is adding some elements to the list. Based on a function call to OuterClass , it should be able to inform the thread to delete elements. What is the best practise? The intention is not to have a blocking data structure (no synchronization) and therefore having a single thread work on List.
Class OuterClass {
List<String> list = new ArrayList<String>();
ListWorker worker = new ListWorker(list);
deleteLastElement() {
worker.setDeleteLastElement(true);
}
}
The worker
ListWorker implements Runnable {
private List<String> list;
private volatile boolean deleteLastElement;
public void setDeleteLastElement(boolean deleteLastElement) {
this.deleteLastElement = deleteLastElement;
}
public ListWorker(List<String> list) {
this.list = list;
}
public void run() {
while(true) {
//add random elements
if(deleteLastElement) {
//delete last element
//set the boolean now to false
}
}
}
This is untested and may need some additional Exception handling but that's roughly it:
ListWorker implements Runnable {
private interface Command{
void execute();
}
private List<String> list;
private BlockingQueue<ListWorker.Command> work; // give it a Blocking Queue impl.
private volatile boolean bAddRandomElements;
public synchronized void deleteLastElement() {
work.add( new Command(){
#Override
public void execute(){ /* delete Last Element of the list */ }
} );
}
public synchronized void startAddingRandom() {
work.add( new Command(){
#Override
public void execute(){ /* set switch bAddRandomElements */ }
} );
}
public synchronized void stopAddingRandom() {
work.add( new Command(){
#Override
public void execute(){ /* reset switch bAddRandomElements */ }
} );
}
public synchronized void terminate() {
work.add( new Command(){
#Override
public void execute(){ /* interrupt thread */ }
} );
}
public ListWorker(List<String> list) {
this.list = list;
}
public void run() {
while(!Thread.interrupted()) {
Command c = null;
if( bAddRandomElements ){
/* add random, assuming you add one random entry per iteration ... */
c = work.poll( /*maybe specify timeout*/ ); // No command - just go on with it! We'll block in next iteration if bAddRandomElements is reset.
}else{
c = work.take(); // blocks until there is a command in queue.
}
if ( null != c ) c.execute();
}
}
public Runnable updater = new Runnable()
{
#Override
public void run() {
obj.notifyDataSetChanged();
}
};
I am new to java, I read that codesnip and wonder when we need such an updater or a class that implements the Runnable interface.
To call that updater, they do this
handler = new Handler();
handler.post(updater);
I don't understand the underlying logic of this.
I don't know the rest of the context, but in that way you select different "behaviours" in your object Handler. As I don't know the context of the code where you saw this example, I'll try to explain it with different classes and methods:
Say, for instance that you want to be able to perform different behaviours in the same piece of code, so you could create new behaviours or select from an existing one, you could have:
class Operation {
Runnable operation = null;
private int result;
private int op1;
private int op2;
public Example(int op1, int op2) {
this.op1 = op1;
this.op2 = op2;
}
// ... more code ...
Runnable sum = new Runnable() {
public void run() { result = op1 + op2; }
}
Runnable minus = new Runnable() {
public void run() { result = op1 - op2; }
}
// ... more code ...
public void selectBehaviour(String behaviourName) {
// ... more code ...
// select behaviour
if("SUM".equals(behaviourName)) {
operation = sum;
} else if("MINUS".equals(behaviourName)) {
operation = minus;
} else {
// ... more code ...
}
}
public void perform() {
operation.run();
}
int getResult() {
return result;
}
}
This case is so common that in Java 8 you will be able to write the code you posted in this way:
public Runnable updater = () -> { obj.notifyDataSetChanged(); }
which is way less verbose.
I'm using ScheduledThreadPoolExecutor and I don't know hot to deal with something.
I'm scheduling some tasks this way:
scheduledExecService = new ExtendedScheduledExecutor(numThreads, myThreadFactory);
TareaActualizacion act = new TareaActualizacion(inst);
ScheduledFuture<?> handle = scheduledExecService.scheduleWithFixedDelay(act, retrasoInicial, segundosRefresco, TimeUnit.SECONDS);
act is a Runnable class that recive some data by parameter:
public class TareaActualizacion implements Runnable {
private Instalacion instalacion;
public TareaActualizacion(Instalacion instalacion) {
this.instalacion = instalacion;
}
#Override
public void run() {
//Do something
}
public Instalacion getInstalacion() {
return instalacion;
}
}
Now in the afterExecute method of the ExtendedSecheduledExecutor I want to get the object Instalacion of the task TareaActualizacion but I don't know how to do it.
My ExtendedScheduledExecutor class looks like this:
public class ExtendedScheduledExecutor extends ScheduledThreadPoolExecutor{
public ExtendedScheduledExecutor(int arg0) {
super(arg0);
}
public ExtendedScheduledExecutor(int arg0, ThreadFactory arg1) {
super(arg0, arg1);
}
#Override
protected void afterExecute(Runnable r, Throwable t)
{
super.afterExecute(r, t);
System.out.println("Executing afterExecute. Throwable is " + t);
if (t != null)
t.printStackTrace();
//I need to get the Instalacion attribute from TareaActualizacion task. How can I do it??
}
}
Any idea of how can I solve it??
Thank you!
Neus
As Stephan already pointed out in https://stackoverflow.com/a/22145530 , you should try to decouple the scheduling and execution from the notification.
One approach for this could be to wrap the actual task (TareaActualizacion) into another implementation of the Runnable interface that only executes the actual task, and afterwards notifies a callback about the task that has been executed.
Depending on your precise requirements, there may be several degrees of freedom for the implementation, but a general approach could roughly look like this:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledTaskNotification
{
public static void main(String[] args) throws Exception
{
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
int n = 3;
for (int i = 0; i < n; i++)
{
UpdateTask updateTask = new UpdateTask(i);
RunnableCallback<UpdateTask> callback = new RunnableCallback<UpdateTask>()
{
#Override
public void runnableFinished(UpdateTask updateTask)
{
System.out.println("Finished "+updateTask+", id "+updateTask.getID());
}
};
Runnable runnableWithCallback =
createRunnableWithCallback(updateTask, callback);
executor.scheduleWithFixedDelay(
runnableWithCallback, 1000, 200+i*200,
TimeUnit.MILLISECONDS);
}
}
static interface RunnableCallback<T extends Runnable>
{
void runnableFinished(T runnable);
}
private static <T extends Runnable> Runnable createRunnableWithCallback(
final T runnable, final RunnableCallback<T> callback)
{
return new Runnable()
{
#Override
public void run()
{
runnable.run();
callback.runnableFinished(runnable);
}
};
}
private static class UpdateTask implements Runnable
{
private final int id;
UpdateTask(int id)
{
this.id = id;
}
#Override
public void run()
{
System.out.println("Run "+this);
}
int getID()
{
return id;
}
#Override
public String toString()
{
return "UpdateTask "+id;
}
}
}
This is a bay way. You should not trying to get the result out of the Executor, because it is only responsible for scheduling and executing tasks, not whats happening inside of them.
Your TareaActualizacion runnable should post the result to another piece of code, where you need it. This can be achieved using a queue or in the easiest case SwingUtilities.invokeLater().