I'm using OpenGL in Java and I have to delete external resources (like vbos). The recommended way is to have a Disposable interface. However doing that would require me to have nearly every class dealing with resources implement this interface. And I've tried that but it's often not clear to me which object should be responsible for calling the dispose() method. That's why I programmed something like this:
public abstract class Destroyable {
private static final ArrayList<Runnable> cleanupTasks = new ArrayList<Runnable>();
public static void cleanup() {
synchronized (cleanupTasks) {
for (Runnable cleanupTask : cleanupTasks) {
cleanupTask.run();
}
}
}
protected abstract void destroy();
#Override
protected void finalize() throws Throwable {
try {
synchronized (cleanupTasks) {
// Let's do cleanup in the main thread as the garbage collector runs in another thread
cleanupTasks.add(new Runnable() {
public void run() {
destroy();
}
});
}
} finally {
super.finalize();
}
}
}
As the garbage collector won't run most of the time I'm calling Destroyable.cleanup() together with System.gc() every five seconds.
It's not that bad if some of the resources aren't destroyed at the end (like static ones) because I'm deleting the context at the end (which destroys the other resources as well).
Is this a good idea or is there a better way of doing this?
Related
In my application I have the following potentially long running classes:
ScheduleLocalNotificationsOperation
UnScheduleLocalNotificationsOperation
SyncEventsToDeviceCalendarOperation
UnSyncEventsToDeviceCalendarOperation
SaveProductsToLocalStorageImpl
and so on.
Most of these are structured this way:
public interface Operation {
void execute();
}
public class ScheduleLocalNotificationsOperation implements Operation {
private MyApplication application;
private List<LocalNotificationDescriptor> localNotifications;
public ScheduleLocalNotificationsOperation (MyApplication application, List<LocalNotificationDescriptor> localNotifications) {
this.application = application;
this.localNotifications = localNotifications;
}
#Override
public void execute() {
// Do some stuff
}
}
Ideally, I would like to design my Operation classes to be concurrency agnostic, and to be able to impose some multithreading policy on them from the outside, like so:
public class MainActivity extends Activity {
public static ExecutorService executorService = Executors.newCachedThreadPool();
#Override
public void onCreate() {
executorService.submit(new Runnable {
#Override
public void run() {
new ScheduleLocalNotificationsOperation(application, createLocalNotificationsList()).execute();
}
});
}
}
But this way I should implement some concurrency policy in every client, every time I call those classes.
On the other hand, I dont want to interrupt the pure logic in those operations by adding concurrency to them, so my question is basically, from design stand point what is the better way to do this, if there is a clearly defined one?
Can I create an OperationsRunner class that will be called by any client and will execute any Operation using polymorphism and make that class be the only one that deals with concurrency?
I have two threads running concurrently, a main thread and a listener that implements Runnable.
The main thread and listener each have a critical section, specifically the method getObjectList(String) in the Manager class that runs in the main thread and handleNewObjects(String, List<Object>) that runs in the listener thread.
My current plan is to make getObjectList() a synchronized method:
class Manager {
protected synchronized getObjectList() {
// Do critical section stuff
}
}
and make handleNewObjects() look like this
class Listener implements Runnable {
private final Manager myManager;
handleNewObjects() {
synchronized (myManager) {
// Do critical section stuff
}
}
}
Will this ensure my critical sections never run simultaneously?
Should I synchronize some other way?
If getObjectList() was to be a synchronized method, and myManager in Listener was the same Manager instance as the instance that will modify a shared set of objects, then yes it would work.
It is hard to say without knowing the relationships between your existing code to know if there's a better solution for you, however this approach could be seen as somewhat fragile. A change to what object Manager locks on would cause Listener to not be thread-safe anymore, and if the shared objects the two critical sections modify already exist in Manager, you might as well have Listener call another synchronized in Manager, say myManager.handleNewObjects().
What I mean by a change to what object Manager locks on is if Manager went from:
protected synchronized getObjectList() {
// Do critical section stuff
}
to
protected getObjectList() {
synchronized (myPrivateFinalLockObject) {
// Do critical section stuff
}
}
or
protected getObjectList() {
delegatingWorkToSomeOtherThreadSafeObject.getObjectList();
}
Then Listener isn't thread-safe anymore as it doesn't lock it's critical section on the same object anymore.
Will this ensure my critical sections never run simultaneously?
Yes, but as Quirliom noted, be sure they are the same object. If you're using any frameworks, beware of framework created proxies.
Should I synchronize some other way?
Producer-consumer setups are pretty common. Things get trickier when you have multiples of each. Rather than reinvent it yourself, you can take a look at some classes that are built into the platform. From the Javadocs (not exactly what you're doing, but close):
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
Assuming that getObjectsList is a retrieval method with no updates, you could improve on concurrency utilizing ReadWriteLocks. Here the handle* method is the method that updates the underlying list. Please see:
http://ilkinbalkanay.blogspot.com/2008/01/readwritelock-example-in-java.html
Just a quick question look at the code below, is there any reason why wouldn't do this or is it fine?
public class MyClass implements Runnable, MyClassInterface {
Thread threader;
void start() {
threader = new Thread(this);
threader.start();
}
#Override
public void run() {
Thread current = Thread.getCurrentThread();
while (threader = current) {
..
}
}
}
The original logic was not to expose that fact it runs in a separate thread to the caller
who creates a "MyClass" but then there are doubts if that is a good thing or bad.
Can anyone see any good reason not to do it or is it acceptable. It can be expected that MyClass.start() maybe called a few times.
EDIT: Updated the code to show it is implementing Runnable and one other interface, the interface is used by client code, the actual implementation may run in a separate thread, same thread or any other way. The idea was to abstract that away from the client, as the client is simply an object that "MyClass" will notify and is not aware (currently) of the Runnable interface it implements.
Perhaps that abstraction is not needed and client should have more control?
EDIT: The start() was simply to tell the object it is ready to start receiving notifications rather than start a thread.
Have a look at this: http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
In my opinion, it is a bad design, because you are breaking encapsulation by implementing an interface (Runnable) and by providing a public method (run) that are of no use of the consumer of the class.
You can start a thread from the start method without inhering from Runnable:
public class MyClass {
private Thread thread;
public void start() {
thread = new Thread(this::doWork); // Java 8 method reference
thread.start();
}
private void doWork() {
// ...
}
}
If you can't use method references from Java 8, replace this::doWork with:
new Runnable() { public void run() { doWork(); } }
I need advice on the following:
I have a #Scheduled service method which has a fixedDelay of a couple of seconds in which it does scanning of a work queue and processing of apropriate work if it finds any. In the same service I have a method which puts work in the work queue and I would like this method to imediately trigger scanning of the queue after it's done (since I'm sure that there will now be some work to do for the scanner) in order to avoid the delay befor the scheduled kicks in (since this can be seconds, and time is somewhat critical).
An "trigger now" feature of the Task Execution and Scheaduling subsystem would be ideal, one that would also reset the fixedDelay after execution was initiated maually (since I dont want my manual execution to collide with the scheduled one). Note: work in the queue can come from external source, thus the requirement to do periodic scanning.
Any advice is welcome
Edit:
The queue is stored in a document-based db so local queue-based solutions are not appropriate.
A solution I am not quite happy with (don't really like the usage of raw threads) would go something like this:
#Service
public class MyProcessingService implements ProcessingService {
Thread worker;
#PostCreate
public void init() {
worker = new Thread() {
boolean ready = false;
private boolean sleep() {
synchronized(this) {
if (ready) {
ready = false;
} else {
try {
wait(2000);
} catch(InterruptedException) {
return false;
}
}
}
return true;
}
public void tickle() {
synchronized(this) {
ready = true;
notify();
}
}
public void run() {
while(!interrupted()) {
if(!sleep()) continue;
scan();
}
}
}
worker.start();
}
#PreDestroy
public void uninit() {
worker.interrup();
}
public void addWork(Work work) {
db.store(work);
worker.tickle();
}
public void scan() {
List<Work> work = db.getMyWork();
for (Work w : work) {
process();
}
}
public void process(Work work) {
// work processing here
}
}
Since the #Scheduled method wouldn't have any work to do if there are no items in the work-queue, that is, if no one put any work in the queue between the execution cycles. On the same note, if some work-item was inserted into the work-queue (by an external source probably) immediately after the scheduled-execution was complete, the work won't be attended to until the next execution.
In this scenario, what you need is a consumer-producer queue. A queue in which one or more producers put in work-items and a consumer takes items off the queue and processes them. What you want here is a BlockingQueue. They can be used for solving the consumer-producer problem in a thread-safe manner.
You can have one Runnable that performs the tasks performed by your current #Scheduled method.
public class SomeClass {
private final BlockingQueue<Work> workQueue = new LinkedBlockingQueue<Work>();
public BlockingQueue<Work> getWorkQueue() {
return workQueue;
}
private final class WorkExecutor implements Runnable {
#Override
public void run() {
while (true) {
try {
// The call to take() retrieves and removes the head of this
// queue,
// waiting if necessary until an element becomes available.
Work work = workQueue.take();
// do processing
} catch (InterruptedException e) {
continue;
}
}
}
}
// The work-producer may be anything, even a #Scheduled method
#Scheduled
public void createWork() {
Work work = new Work();
workQueue.offer(work);
}
}
And some other Runnable or another class might put in items as following:
public class WorkCreator {
#Autowired
private SomeClass workerClass;
#Override
public void run() {
// produce work
Work work = new Work();
workerClass.getWorkQueue().offer(work);
}
}
I guess that's the right way to solve the problem you have at hand. There are several variations/configurations that you can have, just look at the java.util.concurrent package.
Update after question edited
Even if the external source is a db, it is still a producer-consumer problem. You can probably call the scan() method whenever you store data in the db, and the scan() method can put the data retrieved from the db into the BlockingQueue.
To address the actual thing about resetting the fixedDelay
That is not actually possible, wither with Java, or with Spring, unless you handle the scheduling part yourself. There is no trigger-now functionality as well. If you have access to the Runnable that's doing the task, you can probably call the run() method yourself. But that would be the same as calling the processing method yourself from anywhere and you don't really need the Runnable.
Another possible workaround
private Lock queueLock = new ReentrantLock();
#Scheduled
public void findNewWorkAndProcess() {
if(!queueLock.tryLock()) {
return;
}
try {
doWork();
} finally {
queueLock.unlock();
}
}
void doWork() {
List<Work> work = getWorkFromDb();
// process work
}
// To be called when new data is inserted into the db.
public void newDataInserted() {
queueLock.lock();
try {
doWork();
} finally {
queueLock.unlock();
}
}
the newDataInserted() is called when you insert any new data. If the scheduled execution is in progress, it will wait until it is finished and then do the work. The call to lock() here is blocking since we know that there is some work in the database and the scheduled-call might have been called before the work was inserted. The call to acquire lock in findNewWorkAndProcess() in non-blocking as, if the lock has been acquired by the newDataInserted method, it would mean that the scheduled method shouldn't be executed.
Well, you can fine tune as you like.
I saw a Java example that had a main method labeled as synchronized, calling another static synchronized method. The effect is that, basically, the other method runs on the separate thread only after the main method has returned.
What practical functionality would such a construct have?
public class SynchronisedMain {
public static synchronized void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
#Override
public void run() {
thingy();
}
}).start();
System.out.println("Kickstarted thingy thread.");
TimeUnit.MILLISECONDS.sleep(1000);
}
public static synchronized void thingy() {
System.out.println("Thingy!");
}
}
It's probably useful as a makeshift "application closed handler", doing some cleanup duty before the app finishes entirely. It's pretty contrived though...
There is nothing that says the main function can only be used as the entry point to a program. Being static, there is no reason other classes couldn't call SynchronisizedMain.main(). Being synchronized prevents multiple instances from being executed concurrently which might be desirable.