Java function ending after time has elapsed - java

Here's what I want to do. Given a function
public void foo() {
}
I would like to have it end after certain time has elapsed. That is, imagine this is some kind of random generator which has to produce random objects that satisfy some difficult constraints and hence it may or may not succeed under a given time allotment. That is, the function may actually be something like this
public void foo() {
//task1
while(fails) {
//...
}
//task2
while(fails2) {
//...
}
//more tasks may follow, which use the data from the previous tasks to further try to satisfy difficult conditions
}
That is simply just an example. But the point is that the function consists of many while loops, many test cases, and lots of heavy computation.
The goal: I want to be able to say "run foo() and if 4 seconds has elapsed and foo() is still not done, then stop foo() immediately."
What I have tried: I have tried to include conditions on just about every line of foo() to see how much time has elapsed and to return out of the function if the 4 seconds has passed. But given how complicated foo() is, this is clearly very difficult to do code wise because this requires testing the time on every single line of the function.
My thought logic: I think this should be possible because there are functions that do this sort of thing, that terminate code regardless of the state, such as System.exit(1). That is the idea. I'd like to be able to call, from the outside, to have this function foo() terminate.

// foo method and global variables used
private static ArrayList<Integer> foo() {
// info class
class Info {
public boolean run, completed;
public ArrayList<Integer> list;
}
// declare info object, list
final Info info = new Info();
final Object wait = new Object();
// run a new thread
Thread t = new Thread(
new Runnable() {
// run method
#Override
public void run() {
// setup run
info.run = true;
info.completed = false;
info.list = new ArrayList<>();
// loop to modify list. Don't put a big piece of code that will
// take a long time to execute in here.
while(info.run) {
// example of what you should be doing in here:
info.list.add(1);
// and if you are done modifying the list, use:
break;
}
// done modifying list
info.completed = true;
synchronized(wait) {
wait.notify();
}
}
}
);
t.start();
// wait for four seconds, then return list
try {
synchronized(wait) {
wait.wait(4000);
}
} catch (InterruptedException e) { e.printStackTrace(); }
info.run = false;
return info.completed ? info.list : null;
}
// main method
public static void main(String[] args) {
// get list
ArrayList<Integer> list = foo();
System.out.println("Done!");
}
What the foo() method does?
Begins to modify the list it will eventually return
If the time took modifying this list exceeds four seconds, it will stop modifying the list and return the list.
It will return null if the list was stopped early.
It now only uses local variables!
Nice bonus, it will immediately return the list the second modifying it is done.

Submit it as a runnable to an executor service and call get on the returned future with the desired timeout. Then in the catch block for the timeout exception you can cancel the future.
EDIT: Code sample
import com.google.common.base.Throwables;
import java.util.concurrent.*;
public class ExecutorExample {
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
public void example() {
Future<String> future = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
return "Do your complicated stuff";
}
});
try {
future.get(4, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Throwables.propagate(e);
} catch (ExecutionException e) {
//handle
} catch (TimeoutException e) {
future.cancel(true);
}
}
}

Something like this will do the trick, but beware:
public static void main(String[] args){
Runnable fooRunner = new Runnable(){ public void run(){
foo();
}
Thread fooThread = new Thread(fooRunner);
fooThread.start();
Thread.sleep(4000);
fooThread.stop(); //warning -- this is deprecated!
}
The problem is that Thread.stop is deprecated.
Multi-threading in Java is fundamentally a cooperative endeavor. Because foo() may be manipulating shared state, probably protected by a lock that it currently owns, stopping it at an arbitrary point is potentially very dangerous and could lead to unpredictable failures, bugs, etc. later on in the program. (Indeed, since foo's return type is void, it must manipulate some shared state at some point in order to store its result.)
The language does provide a way to tell a thread that it should stop at the next convenient point: Thread.interrupt(), Thread.interrupted(), and InterruptedException. Your foo() method does need to check whether it's been interrupted periodically; that's the way it's done, and any higher-level library constructs (like Future.cancel()) rely on this.

You must enter into the hellish arena of writing threaded code.
http://docs.oracle.com/javase/tutorial/essential/concurrency/
Pseudo code (mutableboolean available in apache commons http://commons.apache.org/lang/download_lang.cgi)
...
final MutableBoolean finished = new MutableBoolean(false);
new Thread(new Runnable(){
public void run() {
doComplicatedStuff(finished);
}
}).start();
Thread.sleep(4000);
finished.setValue(true);

Related

Sharing an ArrayList between two threads?

So I have two threads running where one of them is supposed to get information from the user and the other thread is suppose to work with information supplied by users as follows:
public class UserRequest implements Runnable {
#Override
public void run() {
// TODO Auto-generated method stub
String request;
Scanner input = new Scanner(System.in);
while(true)
{
System.out.println("Please enter request:");
request = input.nextLine();
try
{
//do something
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
And second thread:
public class Poller implements Runnable {
ArrayList<String> colors = new ArrayList<String>();
public void poll()
{
for(String color : colors)
{
if(color == "")
{
//do work
}
else
{
//do work
}
}
}
#Override
public void run() {
colors.add("Violet");
colors.add("Green");
colors.add("Yellow");
colors.add("Orange");
while(true)
poll();
}
}
What I would like to do is take whatever input the user entered inside the UserRequest object and push into the ArrayList in Poller object so it can "work" on the new value as well. I have looked at some thing like BlockingQueue but I don't want either Thread to wait for the other since they have other tasks they need to accomplish in addition to this sharing of data. How can I go about doing this ?
Since you've used the verb 'push' and 'poll', it seems you are looking for a Queue not a List.
Therefore, I think you're looking for the ConcurrentLinkedQueue, documented here.
It allows you to have your UserRequest objects feed it and your Poller objects to consume it.
Though it seems your Poller objects will have quite a high CPU consuption because of the open while not having any wait:
public class Poller implements Runnable {
Queue<String> colors = new ConcurrentLinkedQueue<String>();
public void poll() {
while(this.colors.isEmpty()){
Thread.currentThread().wait();
}
String color = this.colors.poll();
while(color != null) {
if(color == "") {
//do work
} else {
//do work
}
color = this.colors.poll();
}
}
#Override
public void run() {
colors.offer("Violet");
colors.offer("Green");
colors.offer("Yellow");
colors.offer("Orange");
while(true) {
this.poll();
}
}
}
this code needs some changes to run but it contains pretty much everything you need.
What it does is very simple: It keeps polling until there are no elements left.
Once that happens, the Poller object asks it's current Thread to sleep, since there's no point for it to run without elements in the Queue.
public class UserRequest implements Runnable {
#Override
public void run() {
String request;
Scanner input = new Scanner(System.in);
while(true) {
System.out.println("Please enter request:");
request = input.nextLine();
try {
//do something
} catch(IOException e) {
e.printStackTrace();
} finally {
this.notifyAll(); // Notifies all sleeping threads to wake up
}
}
}
If you notice, I've only added a notifyAll call to your UserRequest class. Why? Very simple: notifyAll wakes all waiting Threads which is exactly what all Pollers without elements are doing.
Once it's called, the Pollers will wake, check if their color Queue has elements and work with them. If the Queue has no elements, they will sleep again until a UserRequest wakes them up again and so on and so forth.
There are two ways to solve this problem:
1) It's using thread safe collection, like ConccurentLinkedQueue for logic with producer-consumer, jobs consuming or etc. If you want to use the class that implements List interface (and as a consequence you can take methods same to usual ArrayList), you must look to the side of CopyOnWriteArrayList, but note that this class uses blocking synchronization.
2) Another approach is using built-in java synchronization tools, for example
Semaphore
CyclicBarrier
CountDownLatch
Locks
Phaser
Usual wait/notify mechanism
For more details, you must read the specification. Let's consider an example of using Semaphore:
private final Semaphore semaphore = new Semaphore(2, true);
public void appendToList() throws InterruptedException {
available.acquire();
arrayList.add(.....); //put here what u need
}
public void putItem(Object x) {
if (someLogicHere(x)) //semaphore releases counter in this place
available.release();
}
Of course, you can combine usage all of them, e.g. you can use a few semaphores simultaneously, or use diff tools.
"but I don't want either Thread to wait for the other since they have other tasks they need to accomplish in addition to this sharing of data."
There's no way to accomplish this. Any proper threading of the class will always suffer from the problem that you will need to have one thread wait while the other does something. The point though is you want to minimize that. You want to only cause the thread to stall very briefly and rarely and only in those cases where not doing so will cause it to fault. You can use one of the synchronized data structures or you can just write a little bit of synchronization code yourself.
The only object in question is the arraylist, and you want the absolute minimum amount of stall on either thread. So you would want to synchronize it based on the object of the arraylist itself. So just write a couple little synchronization blocks around the points where you access the arraylist object.
public class Poller implements Runnable {
ArrayList<String> colors;
public Poller(ArrayList<String> colors) {
this.colors = colors;
//pass in colors object, if modified from the scanner side it must synchronize the block around the colors object too.
}
public void doWork(String color) {
//do work
}
public void addColor(String color) {
synchronized (colors) {
colors.add(color);
}
}
#Override
public void run() {
while (!Thread.interrupted())
if (!colors.isEmpty()) {
String color;
synchronized (colors) {
color = colors.remove(0);
}
doWork(color); //work done outside synch
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The point is just never be removing or adding things to the list at the same time. You cannot loop over the list as a whole because if the work is done in-loop it's a problem and the size of the array might change so you don't know how bit it is. But, you can use an ArrayList for this, just synchronize the blocks of code where you change the datastructure and get the string out of that synchronized block and then do work on it. This way the only stall is the brief instant one thread is reading or writing and the other one needs to. Both of which are very fast operations.
If you want access new value entered by the user from poller object then:
As objects are stored in heap , instead of creating a new instance of arrayList in the Poller class you could just send a reference of list object from the UserRequest.So that when yu change add new value to arrayList in userRequest it will be reflected in arrayList being used by Poller.
For Example, You can do it this way:
public class UserRequest implements Runnable {
private ArrayList<String> arrayList = new ArrayList<String>();
#Override
public void run() {
// TODO Auto-generated method stub
String request;
Scanner input = new Scanner(System.in);
while(true)
{
System.out.println("Please enter request:");
request = input.nextLine();
try
{
Poller poller = new Poller(arrayList);
Thread t = new Thread(poller);
t.start();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
You can change your Poller class like this:
public class Poller implements Runnable {
private ArrayList arrayList = null;
Poller(ArrayList<String> arrayList){
this.arrayList = arrayList;
}
public void poll()
{
for(String color : arrayList)
{
if(color == "")
{
//do work
}
else
{
//do work
}
}
}
#Override
public void run() {
while(true){
poll();
}
}
But instead of calling pool in a infinity loop you should add a listener to your arrayList so that you call poll() only when a new value has been added to the List.
You can check out this link to know more about adding listener to a ArrayList: https://stackoverflow.com/a/16529462/7083385
You can use a queue. A queue has its own poll method. You could make it static but i doubt that is the best approach. Generally I use spring to instantiate the queue in some kind of wrapper class but it doesnt look like you are taking that route.

How do I properly shut down a BlockingQueue?

I have a BlockingQueue that processes work events on a single background thread. Various threads call add to add some work to the queue and a single background thread calls take to get the work and process it one a time. Eventually it may be time to stop the processing of work and I want to make sure that the callers who requested work either get their results or get null indicating their work was not done because the BlockingQueue is shutting down.
How do I cleanly stop accepting new work, the best I can think of is to set BlockingQueue field to null and then catch NullPointerException when add is called. Before setting the field to null I will keep a local copy of the pointer so I can drain it after it has stopped accepting work. I think that will work, but it seems a bit hacky, is there a proper way to do this?
Here is what the code looks like now:
ArrayBlockingQueue<Command> commandQueue =
new ArrayBlockingQueue<Command>(100, true);
public boolean addToQueue(Command command) {
try {
return commandQueue.add(command);
} catch (IllegalStateException e) {
return false;
}
}
#Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Command command = commandQueue.take();
// ... work happens here
// result is sent back to caller
command.provideResponseData(response);
}
} catch (InterruptedException e) {
// Break out of the loop and stop
}
// TODO: stop accepting any new work, drain the queue of existing work
// and provide null responses
}
Rather than work with BlockingQueue and a worker thread, consider using a single-thread ThreadPoolExecutor. Something like this:
private class CommandRunner implements Runnable {
public CommandRunner(Command command) {
this.command = command;
}
public void run() {
// ... work happens here
// result is sent back to caller
command.provideResponseData(response);
}
}
private ExecutorService commandExecutor = Executors.newSingleThreadExecutor();
public boolean addToQueue(Command command) {
commandExecutor.submit(new CommandRunner(command));
}
And then your shutdown methods can delegate to the executor.
As mentioned before, use an ExecutorService or ThreadPool, but submit Callables instead of mere Runnables. Have your worker threads observe some stop signal (maybe an AtomicBoolean visible to all of them). If the flag has been set, make the Callables return a special value to indicate that nothing was done. Callers must retain the Future returned by submit to get the Callable's result.
Maybe I should elaborate some more. If you are currently using Runnables, maybe wrap them in Callables and, in call, check the stop flag. If you set the stop flag before you call ExecutorService.shutdown, it will complete the current job normally, but effectively cancel all remaining jobs, therefore draining the remaining queue fast. If you do not shut down, you can even reuse the ExecutorService after resetting the stop flag.
static enum EResult {
Cancelled, Completed
}
static abstract class MyCallable implements Callable<EResult> {
Runnable runner;
public MyCallable( Runnable runner) {
super();
this.runner = runner;
}
}
static AtomicBoolean cancelled = new AtomicBoolean( false);
static void main( String[] argv) {
Runnable runnable = new Runnable() {
#Override
public void run() {
System.out.println( "Done");
}
};
Callable<EResult> callable = new MyCallable( runnable) {
#Override
public EResult call() throws Exception {
if ( cancelled.get()) {
return EResult.Cancelled;
}
runner.run();
return EResult.Completed;
}
};
ExecutorService executorService = Executors.newFixedThreadPool( 1);
// while submitting jobs, change cancelled at some point
Future<EResult> future = executorService.submit( callable);
try {
EResult completeOrNot = future.get();
System.out.println( "result: " + completeOrNot);
} catch ( InterruptedException e) {
e.printStackTrace();
} catch ( ExecutionException e) {
e.printStackTrace();
}
}

I want to test if lazy initialization is thread-safe

I want to test if lazy initialization is thread-safe, so my code is below:
package LazyInit;
import java.util.Random;
public class UnThreadSafeLazyInit {
private ExpensiveObject instance = null;
public ExpensiveObject getInstance() {
if (null == instance) {
instance = new ExpensiveObject();
}
System.out.println("instance=" + instance);
return instance;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++) {
UnThreadSafeLazyInit init = new UnThreadSafeLazyInit();
Task t1 = init.new Task();
Task t2 = init.new Task();
t1.start();
t2.start();
try {
Thread.sleep(4000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(t1.getInstance() == t2.getInstance());
}
}
static class ExpensiveObject {
}
class Task extends Thread {
private ExpensiveObject instance = null;
private Random rand = new Random(47);
public void setInstance () {
this.instance = UnThreadSafeLazyInit.this.getInstance();
}
public ExpensiveObject getInstance() {
return instance;
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(rand.nextInt(1000));
} catch (Exception e) {
e.printStackTrace();
}
setInstance();
}
}
}
In my code, every time I new two Thead task to call public ExpensiveObject getInstance(), in order to prove the two instance maybe not the same reference to ExpensiveObject since race Condition.
When I ran it, it always return true by t1.getInstance() == t1.getInstance().
As I know, if I don't synchronized the function public ExpensiveObject getInstance(), it could be return false since race Condition exists in Lazy Initialization.
I need to find out which code is error.
Thank you.
It is not thread safe, just by inspection of the code. The problem you have is that delays of many milli-seconds is an enormous time to a computer and you are very, very unlikely to see a problem with this type of testing.
For example, the typical delay between updating a volatile field and it being visible to other threads is around 5 nano-seconds. It is for about this long that your solution is not thread safe. You are waiting up up to 1,000,000,000 nano-seconds to see if you get an issue.
This is like trying to see if fireworks lasting 5 seconds went off, but closing your eyes 317 years before concluding there was no fireworks.
Why it is not thread safe has already been covered by others. But I wanted to comment on your title: "I want to test if lazy initialization is thread-safe".
You can't test that a piece of code is thread safe. You might be able to find a test that proves that it is not, but testing only can't prove thread safety:
your test might not interleave threads in a way that reproduces the problem
your test might introduce additional synchronization (for example System.out.println is synchronized) that hides the actual issues
the issue might only appear in a very rare scenario that a few test runs will probably not encounter
the issue might only appear on certain JVMs / CPUs and the fact that your tests "works" with one specific setup does anyway not prove anything
The easiest way would be to make ExpensiveObject a really expensive object:
public class ExpensiveObject {
public ExpensiveObject() {
System.out.println("I'm expensive!");
try {
Thread.sleep(2000L);
}
catch (InterruptedException e) {
}
System.out.println("See. It took 2 seconds to create me!");
}
}
Otherwise, the chance of entering into a rece condition is very small, especially since one thread is started after the other one, and thus calls setInstance() after the other one.
It's not Thread-safe. You're just lucky this time. Modify your code:
public ExpensiveObject getInstance() {
if (null == instance) {
System.out.println("old instance=" + instance);
instance = new ExpensiveObject();
System.out.println("new instance=" + instance);
}
return instance;
}
// In main
Thread.sleep(40); // Thread.sleep(4000);
// In run
Thread.sleep(rand.nextInt(10)); // Thread.sleep(rand.nextInt(1000));
I see a lot of false in my console with this code.

Blocking method calls on an object for a period of time

I'm working on a multithreaded Java project where I would like to have objects that prevent their methods from being called from any thread for some period of time. Ideally, those method calls would not be thrown out, but simply queued up until the cooldown from the previous method has completed. Here's a simple example of a class with that kind of functionality:
public class A {
private synchronized void cooldown(long ms) {
long finishTime = ms + System.currentTimeMillis();
while (System.currentTimeMillis() < finishTime);
}
public synchronized void foo() {
// foo's code
cooldown(1000);
}
public synchronized void bar() {
// bar's code
cooldown(2000);
}
}
This works, but I'm expecting to have quite a few of the above objects and I feel like the loop inside of cooldown() is wasteful. I'd love to use a construct like Thread.sleep(), but in this case, that would have the undesirable effects of forcing the calling thread to sleep and not preventing any other thread from making method calls on A. Any suggestions?
EDIT:
To clarify, given the following implementation:
public synchronized void foo() {
System.out.println("foo");
cooldown(1000);
}
public synchronized void bar() {
System.out.println("bar");
cooldown(2000);
}
public static void main(String[] args) {
final A a = new A();
new Thread(new Runnable() {
public void run() {
a.foo();
}
}).start();
System.out.println("foobar");
new Thread(new Runnable() {
public void run() {
a.bar();
}
}).start();
}
I would like foo and foobar to print instantly (order doesn't matter), followed by bar a second later. If cooldown() just called Thread.currentThread().sleep(ms) instead of the current implementation, then foo would print instantly, followed by foobar and bar a second later.
I'd love to use a construct like Thread.sleep(), but in this case, that would have the undesirable effects of forcing the calling thread to sleep and not preventing any other thread from making method calls on A. Any suggestions?
I don't see the difference between calling Thread.sleep() versus your spin loop aside from the fact that the spin loop wastes CPU. If you are inside cooldown(...) then that instance of A is synchronized.
If you mean that you have other methods that are synchronized and you don't want the thread that is cooling down to be holding the lock then you can use this.wait(...) which will release the lock during the sleep. Of course is someone is calling notify(...) this won't work.
private synchronized void cooldown(long ms) {
try {
long waitUntilMillis = System.currentTimeMillis() + ms;
long waitTimeMillis = ms;
do {
this.wait(waitTimeMillis);
// we need this dance/loop because of spurious wakeups, thanks #loki
waitTimeMillis = waitUntilMillis - System.currentTimeMillis();
} while (waitTimeMillis > 0);
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
}
}
The right thing to do is to not have synchronized methods and only synchronize when you specifically need to. Then you can cooldown easily without holding a lock.
private void cooldown(long ms) {
try {
this.sleep(ms);
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
}
}
public void foo() {
synchronized (this) {
// foo's code
}
cooldown(1000);
}
You have following options:
Thread.sleep() should work fine if called inside synchronized method. All other threads would be prevented and your thread will hold lock and wait.
Use timed wait/notify in a synchronized block. That should also do the job.
EDIT:
See the below code
public class A {
final volatile Object lck = new Object();
volatile boolean waitStatus = true;
private void cooldown(long ms) {
synchronized(lck){
long startTime = System.currentTimeMillis();
//Do thread need to wait
if(waitStatus){
while(System.currentTimeMillis()-startTime < ms)
lck.wait(gapTime);
//Wait over no other thread will wait
waitStatus = false;
}
}
}
public void foo() {
// foo's code
cooldown(1000);
}
public void bar() {
// bar's code
cooldown(2000);
}
}
You are very close already ... minor change ...
private synchronized void cooldown(long ms) throws InterruptedException {
Thead.sleep(ms);
}
Alternatively, you could handle the InterruptedException in the cooldown method itself.
Also, note that your code could actually execute foo, bar, and foobar in any order. The cooldown will slow down the foo or the bar (depending on which gets executed first).
I'd love to use a construct like Thread.sleep(), but in this case,
that would have the undesirable effects of forcing the calling thread
to sleep and not preventing any other thread from making method calls
on A.
Your approach does what you want. Other threads ARE prevented from making method calls on A (if you have synchronized the methods - which you have).

Java signal/event mechanism to indicate some value is available

I have a generator class that owns a Thread in which a number of "records" to be generated is determined, then generates that many records (which get placed in a BlockingQueue for retrieval by another thread).
I'd like the other thread to know how many records are going to be generated (for sensible progress reporting among other things).
It seems Future gives me exactly the interface I'm after, but I'm new to Java, and not sure of the idiomatic way of implementing it.
My background is in C++/Win32, so I'd normally use a win32 "Event" (as created by CreateEvent(0, true, false, 0), with SetEvent and WaitForSingleObject for my signal and wait implementations). I've noticed Java has a CountDownLatch, but this somehow feels heavier than what I'm after (somewhat akin to using an int when I really want a boolean), and it seems unintuitive for this purpose (to me, anyway).
So here's my code using CountDownLatch and a Future. I've distilled my real code down a bit here (removed irrelevant implementation details and ignoring all error handling).
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public abstract class Generator {
private CountDownLatch numRecordsSignal = new CountDownLatch(1);
private int numRecords;
private BlockingQueue<Record> queue = new LinkedBlockingQueue<Record>();
public Generator() {
new Thread(new Runnable() {
#Override
public void run() {
numRecords = calculateNumRecords();
numRecordsSignal.countDown();
for (Record r : generateRecords()) {
try {
queue.put(r);
} catch (InterruptedException e) {
// [ ... snip ... ]
}
}
}
}).start();
}
public Future<Integer> numRecords() {
return new Future<Integer>() {
// Ignore cancel for now (It wouldn't make sense to cancel
// just this part of the Generator's work, anyway).
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
public Integer get() throws InterruptedException {
numRecordsSignal.await();
return numRecords;
}
public Integer get(long timeout, TimeUnit unit)
throws InterruptedException {
numRecordsSignal.await(timeout, unit);
return numRecords;
}
public boolean isCancelled() {
return false;
}
public boolean isDone() {
// Since we can't cancel, just check the state of the
// signal
return numRecordsSignal.getCount() == 0;
}
};
}
public Record nextRecord() throws InterruptedException {
return queue.take();
}
/** --- Boring stuff below this line --- */
public interface Record { }
protected abstract int calculateNumRecords();
protected abstract Iterable<Record> generateRecords();
}
Now for my actual questions:
Is there a better mechanism than CountDownLatch for single-shot signalling?
I want callers to be able to either wait or poll on the result, but don't need them to be able to cancel the operation. Is Future the right way to expose this stuff?
Does any of this stuff look particularly "un-Java"? Am I on the wrong track completely?
Edit:
Just to clarify, I expect the caller to be able to do the following:
Generator gen = new Generator();
Integer numRecords = gen.numRecords().get(); // This call might block waiting for the result
numRecords = gen.numRecords().get(); // This call will never block, as the result is already available.
It's just a slow-to-initialise value I'm trying to implement. Once the "initialised" condition is met, it should latch. The value doesn't get re-evaluated once it's known.
Side comment
You should not start a thread in a constructor - it is very conceivable that the Generator object is not fully created when the thread starts, and the countdown latch could well be null for example. You can create the thread in the constructor, but should start it in a seperate method. Your calling code would become:
Generator g = new Generator();
g.start();
Your question
You are reimplementing a Future yourself, which is not necessary nor desirable in my opinion. I would redesign the class and make Generator implement Callable<Integer> and run it through an executor. That provides you with several things:
remove the threading logic from the Generator, which enables you a more efficient management of your threads at a higher level in your call stack
the integer is returned via the future in your calling code and you rely on the JDK to handle the implementation
I have assumed that it's ok to first populate the queue then return the integer
you can call future.get() as many times as you want - it will only block the first time it is called.
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> future = executor.submit(new GeneratorImpl()); //a concrete implementation of Generator
int numRecords = 0;
try {
numRecords = future.get(); //you can use a get with timeout here
} catch (ExecutionException e) {
//an exception happened in Generator#call()
} catch (InterruptedException e) {
//handle it
}
//don't forget to call executor.shutdown() when you don't need it any longer
}
public abstract class Generator implements Callable<Integer> {
private BlockingQueue<Record> queue = new LinkedBlockingQueue<Record>();
#Override
public Integer call() {
int numRecords = calculateNumRecords();
for (Record r : generateRecords()) {
try {
queue.put(r);
} catch (InterruptedException e) {
// [ ... snip ... ]
}
}
return numRecords;
}
public Record nextRecord() throws InterruptedException {
return queue.take();
}
/**
* --- Boring stuff below this line ---
*/
public interface Record {
}
protected abstract int calculateNumRecords();
protected abstract Iterable<Record> generateRecords();
}
EDIT
If you need to return numRecods asap, you can populate your queue in a separate thread:
public Integer call() {
int numRecords = calculateNumRecords();
new Thread(new Runnable() {
#Override
public void run() {
for (Record r : generateRecords()) {
try {
queue.put(r);
} catch (InterruptedException e) {
// [ ... snip ... ]
}
}
}
}).start(); //returns immediately
return numRecords;
}
The standard Java equivalents of "WaitOnSingleEvent()" and "SetEvent()" for Java threads are "wait()", "notify()" and "notifyAll()".
After looking at implementing my own signal mechanism and following the bread-crumb trail left by others doing the same thing, I came across the javadoc for AbstractQueuedSynchronizer, which includes a code snippet for a "BooleanLatch", which perfectly meets my needs:
class BooleanLatch {
private static class Sync extends AbstractQueuedSynchronizer {
boolean isSignalled() { return getState() != 0; }
protected int tryAcquireShared(int ignore) {
return isSignalled()? 1 : -1;
}
protected boolean tryReleaseShared(int ignore) {
setState(1);
return true;
}
}
private final Sync sync = new Sync();
public boolean isSignalled() { return sync.isSignalled(); }
public void signal() { sync.releaseShared(1); }
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
}
Doing a bit more searching, I found that a number of frameworks include a BooleanLatch (Apache Qpid being one). Some implementations (such as Atlassian's), are auto-resetting, which would make them inappropriate for my needs.
Standard observer notification pattern can be helpful here, if i understood your problem correctly.
For one shot signalling in this scenario Semaphore is better as it remembers the "signal".
Condition object [wait() is on a condition] won't remember the signal.
Semaphore numRecordsUpdated = new Semaphore(0);
In Generator
numRecordsUpdated.release();
In consumer
numRecordsUpdated.acquire();

Categories