Wait for a flag - java

I have to test that a Flash Player is correctly sending requests over the network. For that, I use BrowserMob Proxy to capture traffic.
My issue is I have to wait the end of the video played to test the final request. So as temp solution, in my test, I put a Thread.sleep(videoDuration). But IMO it's not really nice, and overall, the duration can change.
BrowserMob allow to add interceptor on the requests. So I think about notify and wait function.
Here my first try:
protected static boolean percent100Done;
protected static final Object percent100lock = new Object();
#BeforeClass
public static void addInterceptor() {
ProxyServer server = Server.init();
server.addRequestInterceptor((BrowserMobHttpRequest request, Har har) -> {
String percent = request.getProxyRequest().getParameter("percent");
if("100".equals(percent)) {
percent100Done = true;
synchronized (percent100lock) {
percent100lock.notify();
}
}
});
}
#Test
public void testFinalRequest() throws InterruptedException {
driver.get(myurl);
synchronized (percent100lock) {
while (!percent100Done) {
percent100lock.wait();
}
}
//test continue
}
I test this code, and it works. But it seems a bit dirty, especially the new Object line. What happen if I have to add notification for 25, 50 and 75 percents? I will have to 3 others booleans and lock?

Why not store the percentage and have a generic "progress" event, like how XMLHTTPRequest works?
protected static int percent;
protected static final Object progressLock = new Object();
#BeforeClass
public static void addInterceptor() {
ProxyServer server = Server.init();
server.addRequestInterceptor((BrowserMobHttpRequest request, Har har) -> {
synchronized(progressLock) {
percent = Integer.parseInt(request.getProxyRequest().getParameter("percent"));
progressLock.notify();
}
});
}
#Test
public void testFinalRequest() throws InterruptedException {
driver.get(myurl);
synchronized (progressLock) {
int lastPercent = -1;
while (percent != 100) {
if (lastPercent < 50 && percent >= 50) {
System.out.println("50%");
}
lastPercent = percent;
progressLock.wait();
}
}
//test continue
}
In terms of weirdness, I think your solution is fine. It looks strange, but every Object has a lock, so you might as well use it. If you needed to do something more complicated, you might want to look at Lock and it's subclasses. For example, with a ReadWriteLock, multiple readers can hold the lock at the same time, but only one writer can. It doesn't look like you have multiple readers though (and I wouldn't expect locking to effect the performance of this program much).

Related

test if a method behaves in a synchronized way

The below code is a snippet outlining the objective of this unit test. The below demonstrates createFile only performing one task which is already known to be a thread-safe operation.
The idea therefore is more around the test than the actual operation; to prove beyond a shadow of a doubt, the behavior of a thread-safe method in that it behaves in a way that we have already proven historically.
public static final synchronized void createFile(final File file) throws IOException {
file.createNewFile();
}
#Test
public void testCreateFileThreadSafety() throws Exception {
for (int i = 1; i < 50; i++) {
new Thread(new Runnable() {
#Override
public void run() {
try {
createFile(new File(i+".txt"));
new File(i+".txt").delete();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}).start();
assertTrue(file.getParentFile().listFiles().length == 0);
}
}
EDIT:
What's happening now: Thread gets created, file gets created, file gets deleted, thread dies, assert proves nothing and repeat
What's expected: Threads should all start and assert should ensure that only one file gets created at a time and that the other threads are waiting, not executing the method
DOUBLE EDIT:
What I really need is a refactor of the above unit test so that it does what it's supposed to do (as mentioned above)
Of course for this very simple use case, it's quite silly, because the synchronized keyword is right there. But in general, if you want to test if a method is never called concurrently, you can throw in this:
static AtomicInteger c = new AtomicInteger();
public void knownNonThreadSafeMethod(final File file) throws IOException {
int t = c.incrementAndGet();
doSomething();
Thread.yield(); //try to force race conditions, remove in prod
assert t == c.intValue();
}
If you'd use a simple int i.s.o. the AtomicInteger, compiler optimizations would remove the assertion.
static int c = 0;
public void knownNonThreadSafeMethod(final File file) throws IOException {
int t = ++c;
doSomething();
assert t == c; //smart-ass compiler will optimize to 'true'
}
With AtomicInteger, the value is guaranteed to be synchronised over all CPU's and all threads, and thus you'll detect any concurrent accesses.
I know it's not in a JUnit test, but I couldn't find any non-intrusive way to fix this. Maybe you can inject it via AspectJ?
Create File subclass which overrides createNewFile method like this:
class TestFile extends File {
private final AtomicBoolean isCreated = new AtomicBoolean(false);
private boolean isSynchronizationFailed = false;
public boolean createNewFile() throws IOException {
if (isCreated.compareAndSet(false, true)) {
// give other threads chance to get here
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
}
// cleanup
isCreated.set(false);
} else {
isSynchronizationFailed = true;
}
return super.createNewFile();
}
}
Pass instance of this class to your threads
Assert at the end your test that isSynchronizationFailed is false.
If two threads somehow enter createNewFile method at the same time, you will have isSynchronizationFailed variable set to true.

Beginner Java Multithreading issue

I have a problem with a Java multithreaded file crawler that I am making. My issue is that I have a workQueue that is a linkedBlockingQueue that contains the names of files that I would like to crawl over with my threads, each thread will take() from the workQueue and while scanning through the file it may put() another file name into the workQueue (It is a dependency checker program). So I am never really certain when the work is all finished and all threads will eventually enter a waiting state when they try to take() from the (eventually) empty workQueue.
So I guess my question is, is there an efficient way to terminate all of threads once all of the work is finished (when all of threads have entered a waiting state)? Currently I just use sleep() on the main thread and then interrupt() all of the worker threads.
Sorry if the question sounds confused.
I've had this problem before, and the only way I found was to send a special marker object to the BlockingQueue. When the Queue .take() the object, if this is the marker, then the Thread ends itself.
I've tried other solutions, like to wake up the thread and detect the Exception, with no success.
There's a pattern called the Poison Pill that's good for this. Basically, when the producers are done, insert a special value into the queue that tells a consumer to stop. You can either insert one pill for each consumer, or, once a consumer gets a poison pill, return it to the queue for the next consumer. Since it sounds like you're just enqueuing strings, something like
public static final String POISON_PILL = "DONE";
Or in Java 8, use Optional to wrap your values, then have not present be the pill.
BlockingQueue<Optional<...>> queue;
Another option is using an ExecutorService (which is actually backed by a BlockingQueue) and submitting each file as its own task, then using executorService.shutdown() when you're done. The problem with this is that it couples your code more tightly than needed, and it makes it harder to reuse resources like database and HTTP connections.
I'd avoid interrupting your workers to signal them because that can cause blocking IO operations to fail.
You might use the approch below. Add observer pattern if you need to.
Or simply - instead of signalling with a death packet, collect a list of waiting Threads and then interrupt() them.
public class AccessCountingLinkedPrioQueue<T> {
private final LinkedBlockingQueue<T> mWrappingQueue = new LinkedBlockingQueue<>();
private final Object mSyncLockObj = new Object();
private final int mMaxBlockingThreads;
private final T mDeathSignallingObject;
private volatile int mNumberOfThreadsInAccessLoop = 0;
public AccessCountingLinkedPrioQueue(final int pMaxBlockingThreads, final T pDeathSignallingObject) {
mMaxBlockingThreads = pMaxBlockingThreads;
mDeathSignallingObject = pDeathSignallingObject;
}
public T take() throws InterruptedException {
final T retVal;
synchronized (mSyncLockObj) {
++mNumberOfThreadsInAccessLoop;
}
synchronized (mWrappingQueue) {
if (mNumberOfThreadsInAccessLoop >= mMaxBlockingThreads && mWrappingQueue.isEmpty()) signalDeath();
retVal = mWrappingQueue.take();
}
synchronized (mSyncLockObj) {
--mNumberOfThreadsInAccessLoop;
}
return retVal;
}
private void signalDeath() {
for (int i = 0; i < mMaxBlockingThreads; i++) {
mWrappingQueue.add(mDeathSignallingObject);
}
}
public int getNumberOfThreadsInAccessLoop() {
return mNumberOfThreadsInAccessLoop;
}
}
class WorkPacket {
// ... your content here
}
class MultiThreadingBoss {
static public final WorkPacket DEATH_FROM_ABOVE = new WorkPacket();
public MultiThreadingBoss() {
final int THREADS = 7;
final AccessCountingLinkedPrioQueue<WorkPacket> prioQ = new AccessCountingLinkedPrioQueue<>(THREADS, DEATH_FROM_ABOVE);
for (int i = 0; i < THREADS; i++) {
final ThreadedWorker w = new ThreadedWorker(prioQ);
new Thread(w).start();
}
}
}
class ThreadedWorker implements Runnable {
private final AccessCountingLinkedPrioQueue<WorkPacket> mPrioQ;
public ThreadedWorker(final AccessCountingLinkedPrioQueue<WorkPacket> pPrioQ) {
mPrioQ = pPrioQ;
}
#Override public void run() {
while (true) {
try {
final WorkPacket p = mPrioQ.take();
if (p == MultiThreadingBoss.DEATH_FROM_ABOVE) break; // or return
// ... do your normal work here
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
}

Stuck writing to JCSP channel

I have this really simple JCSP(Java Communicating Sequential Processes) code sample in which I'm trying to write an integer to a One2OneInt channel and then read it.
package jcsp;
import org.jcsp.lang.*;
public class JCSP {
public static void main(String[] args) {
One2OneChannelInt chan = Channel.one2oneInt();
chan.out().write(5);
System.out.println("Written...");
System.out.println(chan.in().read());
}
}
It seems that value never gets written on the channel and program just keeps running. "Written..." is never printed out.
So I learned about BlockingQueue and its implementation SynchronousQueue. As stated here, SynchronousQueue works in similar way in which CSP Channels work. This helped me realize what was wrong with my code. Simply put, you can't write and read from channel in same process. Channel is way for processes to communicate.
Similarly to SynchronousQueue's put() which will wait for other process to call take(), CSP Channel's write() which will wait for corresponding read() to be called. The difference is that CSP Channels have objects ChannelOutput and ChannelInput through which objects are written and red. Conversely, you can call put and take directly on instance of SynchronousQueue. Personally, I find SynchronousQueue much easier to understand, which probably relates to JCSP not being very popular.
Still, if you're interested how I made the above code work in JCSP, here it is:
public static class Process1 implements CSProcess {
private ChannelOutputInt output;
public Process1(ChannelOutputInt out) {
output = out;
}
#Override
public void run() {
for (int i = 0; i < 1; i++) {
System.out.println("Written...");
output.write(5);
}
output.write(-1);
}
}
public static class Process2 implements CSProcess {
private ChannelInputInt input;
public Process2(ChannelInputInt in) {
input = in;
}
#Override
public void run() {
int x = 0;
while ((x = input.read()) > 0) {
System.out.println(x);
}
}
}
public static void main(String[] args) {
One2OneChannelInt chan = Channel.one2oneInt();
Process1 process1 = new Process1(chan.out());
Process2 process2 = new Process2(chan.in());
Parallel parallel = new Parallel();
parallel.addProcess(process1);
parallel.addProcess(process2);
parallel.run();
}
The problem is the channel is unbuffered, so your write() call will block until another process reads from the channel. As soon as another process calls read(), 'Written...' will be printed out.
A BlockingQueue with a capacity of 0 behaves similarly to a JCSP channel

Controlling when an automation test ends - Espresso

I have an unusual situation I am testing. I am using Espresso to write my tests. I know Espresso and InstrumentationTestCase is not meant to do this.
I have a Listener I created in one of my classes that will notify me of a change of a certain value. I use the listener in my test suite.
When I get the value from the listener, I need to assert the value was changed as such.
My problem is the test will end before I will receive the value form the listener.
private void sendSpeedChanges() {
setStaticSpeed(new Random().nextInt(10) + 2);
try {
runTestOnUiThread(new Runnable() {
#Override
public void run() {
consoleActivity.onSpeedChanged(getStaticSpeed(), false);
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
private void createSpeedDelegate() {
EspressoMachineValues.setOnSpeedChangeListener(new EspressoMachineValues.OnSpeedChangeListener() {
#Override
public void onSpeedChanged(double speed) {
//assert speed is correct.
assertTrue(getStaticSpeed() == speed);
}
});
}
These are the two methods I am using. The createSpeedDelegate() is call at the very beginning. Then I call sendSpeedChanges. I need to do this X-amount of times.
NOTE:
It takes about 200 milliseconds to retrieve info (On average).
I can't call sendSpeedChanges() until I have checked the value in onSpeedChange()
I cannot use Thread.sleep(); because the listener is on the main thread.
I have tried adding a getInstrumentation().wait(2000); and also getInstrumentation().waitForIdleSync(); Obviously, neither work.
In a perfect world, I would do this:
for (int i = 0; i < 42; i++) {
sendSpeedChanges();
i++;
}
But, this will not wait for the value to be checked. And if I do wait for the value, the test runner thinks all tests are done and terminates.
My question is, would there be a way to control when the test quits? Even though my tests appear to be done.
Alternatively, you could create an IdlingResource to monitor your speed. IdlingResource is the way Espresso uses to verify the Main Thread is idle or that there is no AsyncTasks running in the AsyncTask pool.
Have a loook at coutingIdlingResource class in the library source code. You could implement something similar to that. In your case, it could be something like this:
[...]
private int mTargetSpeed;
private volatile ResourceCallback resourceCallback;
#Override
public boolean isIdleNow() {
boolean isIdle = false;
if (getStaticSpeed() == mTargetSpeed) {
isIdle = true;
resourceCallback.onTransitionToIdle();
} else {
isIdle = false;
}
return isIdle;
}
On your tests, whenever you want to wait for the speed to reach the desired level, you should do:
[...]
SpeedIdlingResource speedIdlingResource = new SpeedIdlingResource ("my_idling_resource");
Espresso.registerIdlingResources(speedIdlingResource);
This way, Espresso will block until your idling resource tells the framework your SpeedMonitor is idle. That's goode because you leverage all Espresso synchronization framework to monitor when you reached the target speed, so your tests would be more reliable and faster than making a occupied wait.
In your test you will need to create a control statement that keeps that test running as long as you want it to be run.
while(myTestNeedsToRun) {
if(speedChangeReceived) {
sendSpeedChange();
speedChangeReceived = false;
}
}
private void createSpeedDelegate() {
EspressoMachineValues.setOnSpeedChangeListener(new EspressoMachineValues.OnSpeedChangeListener() {
#Override
public void onSpeedChanged(double speed) {
//assert speed is correct.
assertTrue(getStaticSpeed() == speed);
speedChangedReceived = true;
}
});
Once you decide you are finished running your test just set myTestNeedsToRun = false and then your test will end.

Java 1.4 synchronization: only allow one instance of method to run (non blocking)?

I have a class proposing translations utilities. The translations themselves should be reloaded every 30 minutes. I use Spring Timer support for that. Basically, my class looks like :
public interface Translator {
public void loadTranslations();
public String getTranslation(String key);
}
loadTranslations() can be pretty long to run, so while it is running the old translations are still available. This is done by loading the translations in a local Map and just changing the reference when all translations are loaded.
My problem is : how do I make sure that when a thread is already loading translations, is a second one also tries to run, it detects that and returns immediately, without starting a second update.
A synchronized method will only queue the loads ... I'm still on Java 1.4, so no java.util.concurrent.
Thanks for your help !
Use some form of locking mechanism to only perform the task if it is not already in progress. Acquiring the locking token must be a one-step process. See:
/**
* #author McDowell
*/
public abstract class NonconcurrentTask implements Runnable {
private boolean token = true;
private synchronized boolean acquire() {
boolean ret = token;
token = false;
return ret;
}
private synchronized void release() {
token = true;
}
public final void run() {
if (acquire()) {
try {
doTask();
} finally {
release();
}
}
}
protected abstract void doTask();
}
Test code that will throw an exception if the task runs concurrently:
public class Test {
public static void main(String[] args) {
final NonconcurrentTask shared = new NonconcurrentTask() {
private boolean working = false;
protected void doTask() {
System.out.println("Working: "
+ Thread.currentThread().getName());
if (working) {
throw new IllegalStateException();
}
working = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!working) {
throw new IllegalStateException();
}
working = false;
}
};
Runnable taskWrapper = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
shared.run();
}
}
};
for (int i = 0; i < 100; i++) {
new Thread(taskWrapper).start();
}
}
}
I am from a .net background(no java experience at all), but you could try a simple static flag of some sort that checks at the beginning of the method if its alrady running. Then all you need to do is make sure any read/write of that flag is synchronized. So at beginning check the flag, if its not set, set it, if it is set, return. If its not set, run the rest of the method, and after its complete, unset it. Just make sure to put the code in a try/finally and the flag iunsetting in the finally so it always gets unset in case of error. Very simplified but may be all you need.
Edit: This actually probably works better than synchronizing the method. Because do you really need a new translation immediately after the one before it finishes? And you may not want to lock up a thread for too long if it has to wait a while.
Keep a handle on the load thread to see if it's running?
Or can't you just use a synchronized flag to indicate if a load is in progress?
This is actually identical to the code that is required to manage the construction of a Singleton (gasp!) when done the classical way:
if (instance == null) {
synchronized {
if (instance == null) {
instance = new SomeClass();
}
}
}
The inner test is identical to the outer test. The outer test is so that we dont routinely enter a synchronised block, the inner test is to confirm that the situation has not changed since we last made the test (the thread could have been preempted before entering Synchronized).
In your case:
if (translationsNeedLoading()) {
synchronized {
if (translationsNeedLoading()) {
loadTranslations();
}
}
}
UPDATE: This way of constructing a singleton will not work reliably under your JDK1.4. For explanation see here. However I think you are you will be OK in this scenario.

Categories

Resources