Create a new Event Handler and Source - java

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

Related

Is there a Future class in JDK which is interruptable and can register a callback straightforwardly?

I'm trying to implement a function which makes a RPC call. (In this function I'd like to set up a thread and try to call remote service infinitely until it succeeds). I want the caller can be notified when it succeeds, also, it should stop trying when the caller decides to cancel the call.
what class should I return in this function?
If return a CompletableFuture, I can register a callback by future.thenRun(), but future.cancel(true) won't interrupt the working thread.
If return a Future/FutureTask, there isn't a straightforward method to register a callback.
To make it concret, I'm looking for something like this:
interface Service {
SomeFutureClass<T> request();
}
The client code may like:
SomeFutureClass<T> future = request();
// I can either register a callback
future.thenRun(() -> {
// someLogic
});
// or tell the service to stop trying
future.cancel(true);
If there isn't such a class, what is the best way to implement function like this?
You could use an Executor and wrap your call.
task is your RPC-Call, listener is your Notification.
With cancel() you can cancel the call, otherwise it reschedules itself until a result occurs.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class RPCCaller
{
ExecutorService service=Executors.newSingleThreadExecutor();
public <V> RepeatedCaller<V> callRepeatedly(Supplier<V> task, Consumer<V> listener) {
return new RepeatedCaller<V>(task, listener);
}
public class RepeatedCaller<V> implements Runnable, Supplier<V> {
private final Supplier<V> task;
private boolean cancel;
private V result;
private Consumer<V> listener;
public RepeatedCaller(Supplier<V> task, Consumer<V> listener) {
this.task = task;
this.listener = listener;
service.execute(this);
}
#Override
public void run() {
try {
result=task.get();
}
catch(Exception ex) {
System.err.println(ex);
}
if(result!=null)
listener.accept(result);
else if(!cancel)
service.execute(this);
}
public void cancel() {
this.cancel = true;
}
public V get() {
return result;
}
}
}

Calling Thread.Sleep in Subscriber thread causes Publisher thread to sleep

I have implemented Publish and Subscribe pattern in my application but when I called Thread.sleep() method in any one Subscriber or any one of my Subscriber throws exception then all others subscribers and publishers gets affected by this so how can I prevent this from happening.
I have created one small demo of above problem
Publisher Code
import java.util.Random;
public class Publisher extends Thread {
Broker broker = Broker.getInstance();
Random random = new Random();
#Override
public void run() {
while (true) {
System.out.println("Published " + new Timestamp(System.currentTimeMillis()));
broker.updateSubscribers(Integer.toString(random.nextInt(250)));
}
}
}
Subscriber Interface
public interface Subscriber {
public void onUpdate(String message);
}
MessageSubscriber code
import java.util.logging.Level;
import java.util.logging.Logger;
public class MessageSubscriber extends Thread implements Subscriber {
Broker broker = Broker.getInstance();
#Override
public void run() {
System.out.println("MessageSubscriber started...");
broker.subscribe(this);
}
#Override
public void onUpdate(String message) {
try {
System.out.println(message);
sleep(1000); // called sleep affects the publisher too
} catch (InterruptedException ex) {
Logger.getLogger(MessageSubscriber.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
As you can see I have called sleep method in MessageSubscriber which also affects the Publisher and makes it sleep too for that duration
Edit added Broker Code
import java.util.ArrayList;
import java.util.List;
/**
*
* #author hemants
*/
public class Broker {
List<Subscriber> subscribersList = new ArrayList<>();
private Broker() {
}
public static Broker getInstance() {
return BrokerHolder.INSTANCE;
}
private static class BrokerHolder {
private static final Broker INSTANCE = new Broker();
}
public void subscribe(Subscriber s) {
subscribersList.add(s);
}
public void unsubscribe(Subscriber s) {
subscribersList.remove(s);
}
public void updateSubscribers(String message) {
subscribersList.stream().forEach(subscriber -> subscriber.onUpdate(message));
}
}
Main class to run above code
public class PubSubPattern {
public static void main(String[] args) {
Publisher publisher = new Publisher();
publisher.start();
MessageSubscriber messageSubscriber = new MessageSubscriber();
messageSubscriber.start();
}
}
Well I have edited my MessageSubscribe code like below and it is doing kind of what I have expected
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author hemants
*/
public class MessageSubscriber extends Thread implements Subscriber {
Broker broker = Broker.getInstance();
#Override
public void run() {
System.out.println("MessageSubscriber started...");
while (true) {
try {
broker.subscribe(this);
System.out.println("subscribed ");
sleep(1000);
broker.unsubscribe(this);
System.out.println("un subscribed");
sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(MessageSubscriber.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
#Override
public void onUpdate(String message) {
System.out.println(message);
}
}
What do you say about this
So you execute sometyhing like this
subscribersList.stream().forEach(subscriber -> subscriber.onUpdate(message));
and during onUpdate you sleep
so its effectively
subscribersList.stream().forEach(subscriber -> Thread.sleep());
or even more verbose
for(Subscriber sub:subscribers){
Thread.sleep(xxx);
}
No wonder it "affects" other listener as caller is blocked here. Caller thread sleeps on every element.
Either use thread pool and submit update tasks, or use subscribersList.parallelStream()
I hope this is only for educational purposes.
You are updating the subscriber in same thread that is why it will affect the other subscriber. And also block the Publisher.
Create new Thread to update the broker and it would be fine.
Here is a quick solution. I updated the MessageSubscriber to keep the usage of the interface Subscriber within the Broker:
public class MessageSubscriber extends Thread implements Subscriber {
Broker broker = Broker.getInstance();
#Override
public void run() {
System.out.println("MessageSubscriber started...");
synchronized (broker) {
broker.subscribe(this);
}
try {
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// TODO OP has to decide how to handle this
// for example
synchronized (broker) {
broker.unsubscribe(this);
}
}
}
#Override
public void onUpdate(String message) {
try {
synchronized (this) {
notify();
}
System.out.println(message);
sleep(1000); // called sleep affects the publisher too
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
Logger.getLogger(MessageSubscriber.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I'm not sure about the handling of the InterruptedException within run() as the lock for boker has to be aquired to enter the synchronized block. Thus it's possible that the thread will wait for this lock instead of interrupting itself effectively.

Java FX Platform.runLater(() -> equivalent for long running Tasks

I learned that in JavaFX the equivalent of
SwingUtilities.invokeLater(new Runnable() {
public void run() {
dosomething();
}
});
might simply be
Platform.runLater(() ->{ dosomething()};
for a long running task I learned that you need to wrap things with a Task like:
Task<Void> task = new Task<Void>() {
#Override
public Void call() {
dosomething();
}
};
new Thread(task).start();
Now it would be great to be able to have a similar lambda shortcut like
TaskLaunch.start(() -> dosomething());
I found
JAVA FX - Lambda for Task interface
Swing timer alternative for JavaFX and the thread management difference
Thread with Lambda expression
discussing some of the issues around this and tried:
package com.bitplan.task.util;
import java.util.concurrent.Callable;
import javafx.concurrent.Task;
/**
* this is a utility task to launch tasks with lambda expressions
*
* #author wf
*
*/
public class TaskLaunch {
/**
*
* #param callable
* #return the new task
*/
public static <T> Task<T> task(Callable<T> callable) {
Task<T> task = new Task<T>() {
#Override
public T call() throws Exception {
return callable.call();
}
};
return task;
}
}
with a JUnit test:
Integer counter=0;
boolean running=false;
public Integer increment() {
running=true;
while (running) {
counter++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
return counter;
}
/**
* #throws Exception
*/
#Test
public void testTaskLaunch() throws Exception {
// https://stackoverflow.com/questions/30089593/java-fx-lambda-for-task-interface
Task<Integer> task=TaskLaunch.task(() -> increment());
try {
Thread.sleep(20);
} catch (InterruptedException e) {
//
}
running=false;
assertTrue(task.get()>10);
}
Which doesn't quite do what I'd like to see yet. The issue seems to be that
the lambda expression runs in the same Thread and the
new Thread(task).start();
part needs to be integrated.
What is needed to get (at least close to) the short one liner mentioned above?
Is a
TaskLaunch.start(() -> dosomething());
feasible?
based on #Damianos proposal https://stackoverflow.com/a/44817217/1497139
I tried:
package com.bitplan.task;
import java.util.concurrent.Callable;
import javafx.concurrent.Task;
/**
* this is a utility task to launch tasks with lambda expressions
*
* #author wf
*
*/
public class TaskLaunch<T> {
Thread thread;
Task<T> task;
Callable<T> callable;
Throwable throwable;
Class<T> clazz;
public Thread getThread() {
return thread;
}
public void setThread(Thread thread) {
this.thread = thread;
}
public Task<T> getTask() {
return task;
}
public void setTask(Task<T> task) {
this.task = task;
}
public Callable<T> getCallable() {
return callable;
}
public void setCallable(Callable<T> callable) {
this.callable = callable;
}
public Throwable getThrowable() {
return throwable;
}
public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}
public Class<T> getClazz() {
return clazz;
}
public void setClazz(Class<T> clazz) {
this.clazz = clazz;
}
/**
* construct me from a callable
*
* #param callable
*/
public TaskLaunch(Callable<T> callable, Class<T> clazz) {
this.callable = callable;
this.task = task(callable);
this.clazz = clazz;
}
/**
*
* #param callable
* #return the new task
*/
public static <T> Task<T> task(Callable<T> callable) {
Task<T> task = new Task<T>() {
#Override
public T call() throws Exception {
return callable.call();
}
};
return task;
}
/**
* start
*/
public void start() {
thread = new Thread(task);
thread.start();
}
/**
* start the given callable
* #param callable
* #param clazz - the return Type class
* #return - the launch result
*/
#SuppressWarnings({ "unchecked", "rawtypes" })
public static TaskLaunch start(Callable<?> callable, Class<?> clazz) {
TaskLaunch<?> launch = new TaskLaunch(callable, clazz);
launch.start();
return launch;
}
}
and changed the test to:
/**
* #throws Exception
*/
#SuppressWarnings("unchecked")
#Test
public void testTaskLaunch() throws Exception {
// https://stackoverflow.com/questions/30089593/java-fx-lambda-for-task-interface
TaskLaunch<Integer> launch = TaskLaunch.start(()->increment(),Integer.class);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
//
}
running=false;
assertTrue(launch.getTask().get()>10);
}
This is close to what i am up to but I get:
java.lang.IllegalStateException: Toolkit not initialized
at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
at javafx.application.Platform.runLater(Platform.java:83)
at javafx.concurrent.Task.runLater(Task.java:1225)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1417)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:745)
At least TaskLaunch now wraps:
Thread
task
callable
a potential Exception/Throwable
the runtime class of the result of the Task
Some of these 5 items might be redundant and available from the standard java concepts. I think at least its handy to have quick access to these after running things from a one liner.
Hope this gets to a working state and thanks for the help!
Just new Thread(() -> dosomething()).start() should do the trick
This is sort of a traditional XY problem.
A Task is much more than just a background thread, hence for this you can use regular threads. It's the beauty of the properties!
The real benefit of using Task is that all state changes and progress updates can safely be observed and bound to a live scene, while doing all the background work on a different thread. It's the work of the class to do the heavy-lifting and call Platform.runLater.
The reason you need a subclass and not a runnable is so you can call its protected updateXxx() methods without worrying for threading issues.
With this said, you'll have no benefit if this would've been a single line code. For this use simple threads.
Hope this helps.
Doing this will cause you to lose the ability to update stuff back to the UI thread natively supported by Task class. On the other hand, I do agree this can be useful if you want to do something in background in "do-and-forget" style.
The problem is just like what you said - you didn't add new Thead() and Thread.start() in. Do this:
public static void runInBackground(Runnable runnable) {
Task<Void> task = new Task<>() {
#Override
public Void call() throws Exception {
runnable.run();
return null;
}
};
new Thead(task).start();
}
runInBackground(() -> System.out.println(Thread.currentThread().hashCode()));
Note that your Task can no longer be non-void, because it cannot return anything back now. Your lambda needs to be able to reference the Task object to return a result asynchronously - that is never going to be possible using lambda.
The answer is now in the question based on Damianos hint.
The workaround for the exception I found is
com.sun.javafx.application.PlatformImpl.startup(() -> {
});
But seems a little bit hacky ...

Any way for a class that has already extended any other class to extend or implement a SwingWorker

I want to extend SwingWorker for a class but I have already extended one other class for that. I wanted to know whether there is some sort of a workaround like in threads (we can extend it or implement it), so that I maybe able to use in doInBackground method of SwingWorker.
I have a list of objects on which I need to perform an operation .The objects are of type A,B,C.
I have made a superclass S and A,B,C are the sub classes for that superclass.
I have an object of S and at runtime while going through the list I find the type of the item in the list and typecast the S to A,B or C and perform the operation .
If I make S a SwingWorker, I can perform the operation only once, since Swing workers can be used only once.
I can't make A,B,C extend SwingWorker because they are already extending S.
So I need to implement SwingWorker for A,B,C
I also have a Connection object that A,B,C would use and I have made it as a Singleton because I don't want to initialize again and again.
An example composition example follows.
Expected output:
Received partial update list [Worker: start]
Progress: 20%...
Progress: 70%...
Progress: 100%...
Received partial update list [Worker: woken up, Worker: sending the
result]
Worker Done
Launcher done.
Code:
package com.stackoverflow;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.SwingWorker;
public class DelegatingSwingWorkerDemo {
public static void main(String[] args) {
new Launcher().launch();
}
}
/**
* Use this, to launch the worker.
*/
class DelegatingSwingWorker<I, O> extends SwingWorker<I, O> {
SwingWorkerable<I, O> delegate;
Publisher<O> publisher;
public DelegatingSwingWorker(SwingWorkerable<I, O> delegate) {
this.delegate = delegate;
publisher = new Publisher<O>() {
#Override
public void publish(O... chunks) {
DelegatingSwingWorker.this.publish(chunks);
}
#Override
public void setProgress(int progress) {
DelegatingSwingWorker.this.setProgress(progress);
}
};
}
#Override
protected void process(List<O> chunks) {
delegate.process(chunks);
}
#Override
protected void done() {
delegate.done();
}
#Override
protected I doInBackground() throws Exception {
return delegate.doInBackground(publisher);
}
}
interface Publisher<O> {
void publish(O... chunks);
void setProgress(int progress);
}
/**
* Make your class implement the interface.
*/
interface SwingWorkerable<I, O> {
void process(List<O> chunks);
I doInBackground(Publisher<O> publisher);
void done();
}
/**
* Let's say this is your super class:
*/
class MySuperClass {
}
/**
* Use your super class, but implement the SwingWorkerable. Then
* launch using a DelegatingSwingWorker
*/
class SleepingDemoSwingWorkerable
extends MySuperClass
implements SwingWorkerable<String, String> {
#Override
public void process(List<String> chunks) {
System.out.println("Received partial update list " + chunks);
}
#Override
public String doInBackground(Publisher<String> publisher) {
publisher.publish("Worker: start");
try {
publisher.setProgress(0);
Thread.sleep(200);
publisher.setProgress(20);
Thread.sleep(500);
publisher.setProgress(70);
Thread.sleep(300);
publisher.setProgress(100);
publisher.publish("Worker: woken up");
} catch (InterruptedException e) {
e.printStackTrace();
}
publisher.publish("Worker: sending the result");
return "Second passed.";
}
#Override
public void done() {
System.out.println("Worker Done");
}
}
final class ConsoleProgressListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent event) {
switch (event.getPropertyName()) {
case "progress":
System.out.println("Progress: " + event.getNewValue() + "%...");
}
}
}
/**
* Launch
*/
class Launcher {
public void launch() {
SleepingDemoSwingWorkerable workerable = new SleepingDemoSwingWorkerable();
DelegatingSwingWorker<String, String> delegatingSwingWorker =
new DelegatingSwingWorker<String, String>(workerable);
delegatingSwingWorker.addPropertyChangeListener(new ConsoleProgressListener());
delegatingSwingWorker.execute();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Launcher done.");
}
}

How to notify all observers without holding the thread?

I have a thread inside a class like this-
import java.util.Observable;
public class Download extends Observable {
private int state = 0;
private final Thread myThread = new Thread(() -> {
/*
some work to do here
*/
setChanged();
notifyObservers(state);
});
public void download(int state) {
if (!myThread.isAlive()) {
this.state = state;
myThread.start();
}
}
public Thread getThread() {
return myThread;
}
public static void MyMethod() throws InterruptedException {
Download down = new Download();
down.addObserver((Observable ob, Object dat) -> {
System.out.println(ob);
if ((int) dat == 1) {
down.download(2);
} else {
System.out.println("success");
}
});
down.download(1);
down.getThread().join();
}
public static void main() throws InterruptedException {
MyMethod();
}
}
The problem is I never get it to print the "success" message.
I assume, it is because all observers are being notified from inside of MyThread. So when down.download(2) is called from the observer inside MyMethod(), the previous thread is still running and the call is ignored.
How can I notify all observers from the main thread, not from the myThread?
You are calling down.download(2) from within the execution of MyThread, therefore the thread is still alive which means that your download method does nothing because of if(!myThread.isAlive()).
I would recommend you to use the Executor framework and Listenable Futures from Guava instead of creating threads manually. Example code from the Guava wiki:
ListeningExecutorService service =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
public Explosion call() {
return pushBigRedButton();
}
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
// we want this handler to run immediately after we push the big red button!
public void onSuccess(Explosion explosion) {
walkAwayFrom(explosion);
}
public void onFailure(Throwable thrown) {
battleArchNemesis(); // escaped the explosion!
}
});
Note that Futures.addCallback(..) also has an overload which allows you to determine which executor should execute the callback, this seems to be what you want.

Categories