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.
Related
Here is my code:
public class ThreadDemo {
public static void main(String args[]) throws Exception {
Printer[] printers = new Printer[5];
printers[0] = new Printer("#base");
printers[1] = new Printer("#try");
printers[2] = new Printer("!test");
printers[3] = new Printer("^hello");
printers[4] = new Printer("*world");
for (Printer x : printers) {
x.start();
}
try {
for (Printer y : printers) {
y.join();
}
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
class Printer extends Thread {
public Printer(String name) {
super(name);
}
public void run() {
print();
}
public synchronized void print() {
for (int i = 0; i < 10; i++) {
System.out.print(getName().charAt(0));
try {
sleep(100);
} catch (InterruptedException e) {
System.out.println(e + " occured");
}
}
}
}
It results in
#^!#**#^!#*##!^#*#^!#^!*#^*#!##!#*^##^!*!#^#*##*^!
My expectation is that all symbols would be serialized as #####^^^^^ based on which thread starts first.
Calling sleep() would let other threads to proceed until sleeptime of current thread , but i guess that should not be the case with synchronized method.
The synchronised doesn't come into play here.
That keyword makes sure that you can't invoke the same method on the same object in parallel.
You are invoking it on different objects, therefore the result would be the same even without the keyword in place!
( I rather assume that the result you see is in fact caused by using println() here. That is a "really slow" operation that introduces "de facto" synchronisation when used by threads that are super-quick doing all their other work. I am trying to find some additional information about that, but that might take some more time )
The issue with your code or I would say your expectation is that the method print is synchronized at the object level and you are creating new thread objects, starting the thread and calling this method.
So in this case, each method is synchronized on each individual thread object. To achieve the behavior you expect, we can make the print method static and see the behavior change. You will get the expected result because then, the method print is synchronized on a single instance of Printer class lock. So even if different threads instance are calling this method, because there is a single lock for class, thread execution happens sequentially.
public static synchronized void print() {
for (int i = 0; i < 10; i++) {
System.out.print(Thread.currentThread().getName().charAt(0));
try {
sleep(100);
} catch (InterruptedException e) {
System.out.println(e + " occured");
}
}
}
#SolomonSlow - So it has to be corrected as 'No Synchronized methods' can be called on the same object at same time ?
There is only one thing you will ever need to know about a synchronized instance method. You need to know that this...
synchronized void Foobar() { ... }
...Is just a shortcut way of writing a synchronized block.
void Foobar() {
synchronized (this) {
...
}
}
Both of those method declarations do exactly the same thing. So, everything you know or learn about how synchronized blocks behave can be applied to synchronized methods too.
The most important thing to know about synchronized blocks is, "No two threads can ever be synchronized on the same object at the same time." If you understand that, and if you know how a synchronized method is just a shortcut for a synchronized block, then you can answer your own question.
I have the following method and I am struggling to get 100% code coverage.
public final class SleepingHelper {
public static void sleepInMillis(Duration timeOfNextTry) {
try {
Thread.sleep(timeOfNextTry.toMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The question is how can I force Thread.sleep to throw an exception?
Edit: since it was marked as duplicate, I am still wondering what I would assert in the test ? The other question Is more generic.
You need to interrupt it from another thread. For example:
Thread t = new Thread() {
public void run () {
SleeperMillis.sleepInMillis(new Duration(10000000l));
}
}.start();
Thread.sleep(100); // let the other thread start
t.interrupt;
You don't need to actually interrupt the thread. You can use PowerMockito to mock the static method Thread.sleep()
#RunWith(PowerMockRunner.class)
#PrepareForTest(Thread.class)
public class TestClass {
#Test
public void testSleepInMillis() throws Exception {
PowerMockito.mockStatic(Thread.class);
PowerMockito.doThrow(new InterruptedException ()).when(Thread.class);
try {
SleepHelper.sleepInMillis(11);
fail("expected exception");
} catch (InterruptedException e) {
System.out.println("all good");
}
}
You don't test it, because you can't assert its results, and you can't assert it because Thread.sleep is not accurate or guaranteed to sleep for this duration of time, and the test results will differ from run to run.
Mocking is a better option here.
Btw, it is not just that your tests aren't predictable, your code that uses Thread.sleep in production is going to be unpredictable for the same reasons. Thread.sleep(some magic number goes here) usually indicates a badly written program.
I wouldn't bother testing it. 100% coverage is excessive. However, you could do it like this:
#Test
public void testException() throws Exception {
// Capture the system error stream, so that we can test that the expected exception is printed.
ByteArrayOutputStream capturedErrors = new ByteArrayOutputStream();
System.setErr(new PrintStream(capturedErrors));
// Create a new thread on which to run the candidate method.
Thread thread = new Thread() {
#Override
public void run() {
SleepingHelper.sleepInMillis(Duration.ofMillis(10));
}
};
// Start the second thread.
thread.start();
// Interrupt the second thread. (The candidate method hasn't finished yet. It takes 10 milliseconds to run.)
thread.interrupt();
// Wait for the thread to die (and write out the stack-trace).
thread.join();
// Test that the expected exception's stack trace was printed to the system error stream.
// The output should start with the exception's name.
String output = capturedErrors.toString();
int lengthOfExceptionName = "java.lang.InterruptedException".length();
assertEquals(output.substring(0, lengthOfExceptionName), "java.lang.InterruptedException");
}
Suppose something like the following:
public boolean doThisThing(SomeArg arg) {
if(iAmAllowedToDoIt()) {
doThing(arg);
return true;
} else {
return false;
}
Suppose that iAmAllowedToDoIt() is a very expensive method, and doThisThing() is invoked by many threads concurrently, and I am allowed to do everything given that I am allowed to do anything, is there a way to batch invocations of iAmAllowedToDoIt() such that I would accumulate SomeArgs in a concurrent data structure, and invoke doThing on all of them at once after resolving iAmAllowedToDoIt only one time without modifying the API? What would that code look like? I can't figure out how to do multithreaded batching performantly like this without modifying the API. An ideal answer would include something that doesn't rely on blocking for a fixed period of time to accumulate invocations of doThisThing().
Ideally it would end up as something like:
Call doThisThing
Call iAmAllowedToDoIt asynchronously
All calls to doThisThing before (2) retuns block until (2) returns
(2) Returns, if true invoke doThing for all blocked doThisThing()s
Your containing object could have an AtomicReference that holds a CompleteableFuture for the computation of iAmAllowedToDoIt(). Additional invocations of doThisThing() simply await the completion of the completable future if one is present or create a new one otherwise, with an appropriate CAS loop to avoid creating more than one instance at a time.
Upon completion the reference is set to null again so that threads invoking the method at a later point can start a new computation.
You could do the following (which implements an algorithm similar to the one proposed by #the8472) :
public class Test {
/**
* Lock used to guard accesses to allowedFuture
*/
private final Object lock = new Object();
/**
* The future result being computed, reset to null as soon as the result is known
*/
private FutureTask<Boolean> allowedFuture = null;
private static final Random RANDOM = new Random();
public boolean doThisThing() throws ExecutionException, InterruptedException {
if (iAmAllowedToDoIt()) {
System.out.println("doing it...");
return true;
}
else {
System.out.println("not doing it...");
return false;
}
}
private boolean iAmAllowedToDoIt() throws ExecutionException, InterruptedException {
// if true, this means that this thread is the one which must really compute if I am allowed
boolean mustCompute = false;
// The Future holding the result which is either the cached one, or a new one stored in the cache
FutureTask<Boolean> result;
synchronized (lock) {
// if no one has computed the result yet, or if it has been computed and thus must be recomputed
// then create it
if (this.allowedFuture == null) {
mustCompute = true;
this.allowedFuture = new FutureTask<>(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
System.out.println("computing if I am allowed...");
Thread.sleep(RANDOM.nextInt(3000));
boolean allowed = RANDOM.nextBoolean();
System.out.println(allowed ? "allowed!" : "not allowed!");
return allowed;
}
});
}
result = this.allowedFuture;
}
if (mustCompute) {
allowedFuture.run();
// reset the cache to null, so that the next thread recomputes the result
synchronized (lock) {
this.allowedFuture = null;
}
}
return result.get();
}
public static void main(String[] args) {
Test test = new Test();
Runnable r = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(RANDOM.nextInt(6000));
test.doThisThing();
}
catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
};
for (int i = 0; i < 50; i++) {
Thread t = new Thread(r);
t.start();
}
}
}
I am trying to play an mp3 file on button press or selection from a list (which I have managed successfully). However, I cannot seem to stop the song being played multiple times on the same button press.
What I would like to do is play the song in a new thread, disable playing the song again until the thread has closed, then allow playing again.
My code is as follows:
public class SoundFactory {
private Player player;
private static boolean running = false;
private String getFile(String name) {
String f = "sound" + File.separator + name + ".mp3";
return f;
}
public void playMP3(String name) {
if (!running) {
running = true;
try {
FileInputStream fis = new FileInputStream(getFile(name));
BufferedInputStream bis = new BufferedInputStream(fis);
player = new Player(bis);
} catch (Exception e) {
System.out.println("Problem playing file " + name);
System.out.println(e);
}
// run in new thread to play in background
new Thread() {
public void run() {
try {
player.play();
} catch (Exception e) {
System.out.println(e);
}
}
}.start();
//running = false;
}
}
public void close() {
if (player != null) player.close();
}
}
The file is played via:
SoundFactory sf = new SoundFactory();
sf.playMp3("song name");
on a JButton click
I am new to threading so I apologise in advance if this has an obvious solution!
It sounds to me like you are getting multiple click events fired at once instead of just one. A little logging should verify this. Your method as is, is wide open to race conditions.
The two events can be so close together that when the one checks running it see !running as true. Before that one can do running = true, the second event also sees !running as true and enters the if clause. They then both set running to true and spawn a thread to play the mp3.
What you need to do is make your method synchronized.
public synchronized void playMP3(String name)
http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
If count is an instance of SynchronizedCounter, then making these
methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing
a synchronized method for an object, all other threads that invoke
synchronized methods for the same object block (suspend execution)
until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent
invocation of a synchronized method for the same object. This
guarantees that changes to the state of the object are visible to all
threads.
Just to clarify my last comment, here is a test program showing where running = false should be placed.
public class Test {
public static boolean running = false;
public synchronized void runner() {
if(!running) {
running = true;
System.out.println("I'm running!");
new Thread() {
public void run() {
for(int i=0; i<10000; i++) {} // Waste some time
running = false; // This is only changed once the thread completes its execution.
}
}.start();
} else {
System.out.println("Already running.");
}
}
public static void main(String[] args) {
Test tester = new Test();
tester.runner();
tester.runner(); // The loop inside the Thread should still be running so this should fail.
for(int i=0; i<20000; i++) {} // Waste even more time.
tester.runner(); // The loop inside the Thread should be done so this will work.
}
}
It outputs:
I'm running!
Already running.
I'm running!
It's been years since I've worked with Swing and had forgotten that its event dispatcher is single threaded. So your issue is more likely this than a race condition. It still doesn't hurt to get into writing things to be thread safe from the beginning as it gets you used to it and thinking that way.
Definite warning on using the synchronized method... It can be horrible on performance if only a small part of your method needs to be synchronized. In this case your whole method needs to be thread safe.
If only a small part needs to be thread safe you need to use synchronized blocks.
Thread safe per instance:
public class myClass {
public void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(this) {
// Code that needs to be thread safe per instance
}
// More code that doesn't need thread safety.
}
}
Thread safe across all instances.
public class myClass {
static Object lock = new Object();
public void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(lock) {
// Code that needs to be thread safe across all instances.
}
// More code that doesn't need thread safety.
}
}
Thread safe in a static method.
public class myClass {
public static void myFunc() {
// bunch of code that doesn't need to be thread safe.
synchronized(MyClass.class) {
// Code that needs to be thread safe.
}
// More code that doesn't need thread safety.
}
}
Probably way more information than you want, but I've just seen threaded programming taught so poorly many, many times.
You need to call JButton.setEnabled(false); right before you start playing the mp3, and then call JButton.setEnabled(true); when the mp3 finishes playing.
Obviously, you should replace JButton with your button's object (eg: playButton.setEnabled()).
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.