So I had a crack at coding my own AsyncTask class like system that runs on a ThreadPoolExecutor natively. Everything was working fine until I decided to implement the progress side of things. The progress works much like AsyncTask, the onProgressUpdate function is called on the UI thread. The problem I'm experiencing is that whenever there is a System.out or Log.x line in the onProgressUpdate it hangs indefinitely with no error or warning oddly. The code is as below:
public abstract class Task<A, B> {
private static final Executor EXECUTOR = getExecutor();
private static final int DEFAULT_PRIORITY = Thread.MIN_PRIORITY;
private static final int DEFAULT_PROGRESS_INCREMENT = 1;
private static final Executor getExecutor() {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
executor.setCorePoolSize(1);
executor.allowCoreThreadTimeOut(false);
// TODO set rejection handler
//executor.setRejectedExecutionHandler(new Handler());
// TODO set thread factory
executor.prestartCoreThread();
return executor;
}
public static class ExecutionListener<B> {
public void onPreExecute() {
Log.i("TASK", "Pre - Thread: " + Thread.currentThread().getId());
}
public void onPostExecute(B output) {
Log.i("TASK", "Post - Thread: " + Thread.currentThread().getId() + " - Output: " + output);
}
public void onProgressUpdate(int progress) {
Log.d("TASK", "Hello");
}
}
private Handler handler;
private ExecutionListener<B> executionListener;
private volatile int progress = 0;
private AtomicBoolean progressPublished = new AtomicBoolean(true);
private B output;
public Task() {
this.handler = new Handler();
this.executionListener = new ExecutionListener();
}
public void setExecutionListener(ExecutionListener executionListener) {
if(executionListener == null) {
this.executionListener = new ExecutionListener();
}
else {
this.executionListener = executionListener;
}
}
protected void updateProgress(int progressMade) {
Log.d("TASK", "Test");
progress += progressMade;
if(progressPublished.compareAndSet(true, false)) {
if(!handler.post(new Runnable() {
#Override
public void run() {
Log.d("TASK", new Integer(progress).toString() + " - a");
executionListener.onProgressUpdate(progress);
// Hangs below
progressPublished.lazySet(true);
Log.d("TASK", new Integer(progress).toString() + " - b");
}
})) {
Log.d("TASK", "Failed to post");
}
}
}
protected void updateProgress() {
updateProgress(DEFAULT_PROGRESS_INCREMENT);
}
protected abstract B doTask(A input);
public void execute(final A input, final int priority) {
EXECUTOR.execute(new Runnable() {
#Override
public void run() {
Thread.currentThread().setPriority(priority);
handler.post(new Runnable() {
#Override
public void run() {
executionListener.onPreExecute();
}
});
output = doTask(input);
if(!handler.post(new Runnable() {
#Override
public void run() {
Log.d("TASK", "Done");
executionListener.onPostExecute(output);
}
})) {
Log.d("TASK", "Failed to post post");
}
}
});
}
public void execute(final A input) {
execute(input, DEFAULT_PRIORITY);
}
}
The ExecutionListener is just a class to override the methods to be run on the UI much like AsyncTask's methods for doing the same. The code uses Runnable objects to execute the doTask method and send updates / the result to the appropriate method in the ExecutionListener.
The Thread.currentThread() parts are just to ensure things are running on the thread I intended them to. The problem only shows itself when running a Task that frequently calls updateProgress() - I have tried putting a thread sleep in the onProgressUpdate() method and that seems so solve things, though that obviously isn't a good solution.
It also only seems to have a problem with Log.x / System.out - I don't know whether the call frequency of either of them could cause this kind of issue. I'm at a loss with this progress feature and logging so any advice would be greatly appreciated - I've also found this quite hard to explain so please ask if you need me to clarify anything!
Turns out the Thread.currentThread().getId() is at fault. Removing that part fixes everything. Follow up question here: Is Java Thread getId() thread-safe?
Related
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've a core method in my project which I need it to be synchronized in order not to be accessed twice at the same time, and hence I have a thread which uses an instance from this class to access this method, but inside this thread I need to have a long life loop to be used to access the same method with a fixed value so I have to use another thread in order to allow the first thread to move on and complete it's duties, but for sure the method doesn't run from that second thread using the same instance used in the first thread, and somehow I can't instantiate another instance from the class as I have to use this instance exactly, so how to overcome this problem.
below is the problem translated to java:
public class ClassOne {
synchronized public void my_method(int number) {
// Do some Work
}
}
public class ClassTwo {
private void some_method() {
Thread one = new Thread(new Runnable() {
#Override
public void run() {
ClassOne class_one = new ClassOne();
// DO Work
class_one.my_method(0);
run_loop(class_one);
// Complete Work
}
});
one.start();
}
boolean running = true;
private void run_loop(final ClassOne class_one) {
Thread two = new Thread(new Runnable() {
#Override
public void run() {
while (running) {
class_one.my_method(1); // won't run
Thread.sleep(10000);
}
}
});
two.start();
}
}
Actual problem overview:
my_method --- > is to send UDP packets.
the method has to be synchronized otherwise I'll get the socket is already open exception when trying to use it more than once repeatedly.
at some point, I have to send a KeepAlive message repeatedly each 10 seconds, so, I have to launch a separate thread for that which is thread two in run_loop method.
Putting something that will compile and work. I don't see why you need this function to be synchronized. Check the output for this program...The second thread access this method only when the first thread is done accessing (unless you have missed adding some additional code).
class ClassOne {
int criticalData = 1;
synchronized public void my_method(int number) {
// Do some Work
criticalData *= 31;
System.out.println("Critical data:" + criticalData + "[" + Thread.currentThread().getName() + "]");
}
}
class ClassTwo {
boolean running = true;
public void some_method() {
Thread one = new Thread(new Runnable() {
public void run() {
ClassOne class_one = new ClassOne();
// DO Work
class_one.my_method(0);
run_loop(class_one);
// Complete Work
}
});
one.start();
}
public void run_loop(final ClassOne class_one) {
Thread two = new Thread(new Runnable() {
public void run() {
while (running) {
class_one.my_method(1); // won't run
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
two.start();
}
}
public class StackExchangeProblem {
public static void main(String[] args) {
ClassTwo two = new ClassTwo();
two.some_method();
}
}
In the last days I have found myself using this approach for asynchronously performing some long operation (several seconds), and then return some value via a callback that must execute on the caller thread, which is typically but not necessarily the UI thread.
public abstract class DoSomethingCallback
{
public abstract void done(Object result);
}
public void doSomething(final Object param, final DoSomethingCallback doSomethingCallback)
{
// Instantiate a handler for the calling thread
final Handler handler = new Handler();
// Start running the long operation in another thread
new Thread(new Runnable() {
#Override
public void run() {
// Do a long operation using "param" as input...
Object result = longOperation(param);
// Return result via a callback, which will run in the caller thread
handler.post(new Runnable() {
#Override
public void run() {
doSomethingCallback.done(clearBytes);
}
});
}
}).start();
}
This seems to work pretty well and is very simple to use. However, I somehow suspect it might have some problems I'm not aware of. So the question is, what are the potential issues of this approach? What are better alternatives than manually creating and running a thread? I'm seeking for simplicity and robustness.
The only problem is that such approach breaks encapsulation: the second thread not only computes the result, but also dictates what the caller thread should do with it. So I'd better refactor your code as follows:
public abstract class DoSomethingCallback {
final Handler handler = new Handler();
public void post(final Object result) {
handler.post(new Runnable() {
#Override
public void run() {
doSomethingCallback.done(result);
}
});
}
public abstract void done(Object result);
}
public void doSomething(final Object param, final DoSomethingCallback doSomethingCallback) {
// Instantiate a handler for the calling thread
final DoSomethingCallback handler = new DoSomethingCallback () {
void done(Object result) {
...
}
};
// Start running the long operation in another thread
new Thread(new Runnable() {
#Override
public void run() {
// Do a long operation using "param" as input...
Object result = longOperation(param);
// Return result via a callback, which will run in the caller thread
handler.post(result);
});
}
}).start();
}
I have a threadfactory, executor, thread class and a runnable class.
Here is the thread class: (threadsCount is an AtomicInteger that I use to keep track of number of threads created)
public void run() {
try {
threadsCount.incrementAndGet();
super.run();
} finally {
threadsCount.decrementAndGet();
}
}
and my runnable class is currently not implemented but has empty run() method.
When I try to call Executor.execute(new RunnableClazz()), control comes to this Thread class - run() method and when it encounters super.run(), it goes to the RunnableClazz#run() method.
All these are fine. But problem is, after the RunnableClazz#run() is completed, the control doesn't come back to 'finally' block of my Thread class.
Any ideas? Do I need to manully kill the runnable at the end of run() method?
public class ThreadAA extends Thread {
private static final AtomicInteger threadsCount = new AtomicInteger();
private static final AtomicInteger threadsCreated = new AtomicInteger();
public static final String DEFAULT_NAME = "ThreadAA";
public ThreadAA(Runnable r)
{
this(r, DEFAULT_NAME);
}
public ThreadAA(Runnable r, String threadName)
{
super(r, threadName + "-" + threadsCreated.incrementAndGet());
setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Throwable e)
{
logger.error("Uncaught exception in thread " + t.getName(), e);
}
});
}
#Override
public void run()
{
boolean debug = false;
//just for debug purpose
debug = true;
if(debug)
{
logger.debug("Running thread " + getName());
}
try
{
threadsCount.incrementAndGet();
super.run();
}
finally
{
threadsCount.decrementAndGet();
if(debug)
{
logger.debug("Done running thread " + getName());
}
}
}
}
My RunnableClass:
public class RunnableClazz implements Runnable {
#Override
public void run() {
logger.debug("Inside RunnableClazz");
}
}
The method that calls this runnable looks like this:
Executor executor = new Executor(25, 100, 1L, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(5), new TFactory("abc"));
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.execute(new RunnableClazz());
executor.execute(new RunnableClazz());
Please note that, I create the executor just once during server startup. I have pasted it just to give an idea on how I create it.
So executor.execute(new RunnableClazz()); creates the issue.
I copied your code and started debugging.
When you call super.run() it runs the one from ThreadPoolExecutor:
public void run() {
runWorker(this);
}
runWorker then calls RunnableClazz.run(), and after that is finished, it puts the thread on hold, waiting for new runnables to be executed. How did this happened?
In the threadFactory, which I assume it's something like this:
public Thread newThread(Runnable r) {
return new ThreadAA(r);
}
the Runnable r is not your RunnableClazz, but the ThreadPoolExecutor.
EDIT:
You may want to extend the ThreadPoolExecutor class and implement the methods:
protected void beforeExecute(Thread t, Runnable r) { }
protected void afterExecute(Runnable r, Throwable t) { }
and implement your counting there.
Each time a back-end message comes I add it to JList and JList is being refreshed using fireIntervalAdded. The problem is that in one second 20 messages may arrive and each one of them will call fireIntervalAdded. What I would like to do is to stack all messages in List and send one big stack of data to JList. My current solution does not seem to work, it always sends one message instead of one big stack:
private class StackingListener implements MessageListener {
private List<Message> messages = new LinkedList<Message> ();
private int waiting = 0;
#Override
public void messageReceived(MessageEvent event) {
stackData(event.getData());
}
private void stackData(Message data) {
messages.add(data);
if (waiting <= 0) {
waiting = 3;
new Thread(new Runnable() {
#Override
public void run() {
while(--waiting > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
List<Message> list = new ArrayList<Message>(messages);
messages.clear();
logger.info("Adding list with size of " + list.size());
controller.getListModel().addFullElements(list);
}
}).run();
} else {
waiting = 3;
}
}
}
I think I'm doing something very wrong. The idea of this code is to stack up messages while Thread is sleeping. But seems like Thread.sleep stops everything, not only the current thread.
Thanks
You are using Thread.run() which just calls the run() method in the current thread. What you intended to use was Thread.start() creates a thread and call run() in that new thread.
However I wouldn't structure the code like this at all. I believe a simpler apporach is to use a queue.
class StackingListener implements MessageListener, Runnable {
private final BlockingQueue<Message> messages = new LinkedBlockingDeque<Message>();
private final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); {
service.scheduleAtFixedRate(this, 500, 500, TimeUnit.MILLISECONDS);
}
#Override
public void messageReceived(MessageEvent event) {
messages.add(event.getData());
}
#Override
public void run() {
final List<Message> list = new ArrayList<Message>();
messages.drainTo(list);
logger.info("Adding list with size of " + list.size());
// add to the GUI component in a thread safe manner.
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
controller.getListModel().addFullElements(list);
}
});
}
public void stop() {
service.shutdown();
}
}