class PublishService {
public void longRunningPublish() {
...
}
}
From different places in code, the method can be invoked.
caller1.longRunningPublish();
caller2.longRunningPublish();
...
callerN.longRunningPublish();
Question: how can I prevent longRunningPublish running concurrently? Each invocation should stack and be delay, and only start when the previous run has finished.
Could I do better than the following?
class PublishService {
private boolean running;
public void throttleLongRunningPublish() {
while (running) {
TimeUnit.SECONDS.sleep(10);
}
running = true;
try {
longRunningPublish();
} finally {
running = false;
}
}
}
Your code is not thread safe.
If you create multiple instances of PublishService and run them concurrently the boolean variable has no effect.
If your instance of PublishService is a singleton and the same class is executed by different threads there there is no guarantee that the method will be executed serially because multiple thread could enter the method before reaching the instruction:
running = true;
This is a simple example than handles serialization if there are multiple instances of the same class along with a "demo" main
public class PublishService {
private static final Logger logger= LoggerFactory.getLogger(PublishService.class.getName());
private static final Lock lock=new ReentrantLock();
public void longRunningPublish() {
lock.lock();
try {
logger.info("{} longRunningPublish before sleep",Thread.currentThread().getId());
Thread.sleep(500);
logger.info("{} longRunningPublish after sleep",Thread.currentThread().getId());
} catch (InterruptedException e) {
logger.error(e.getMessage(),e);
} finally {
lock.unlock();
}
}
public static void main(String args[]) {
ExecutorService executor=Executors.newFixedThreadPool(10);
for(int i=0;i<20;i++) {
executor.submit(() -> {
PublishService publishService = new PublishService();
publishService.longRunningPublish();
});
}
}
}
If the class is a singleton you can remove the static qualifier of the lock variable.
In order to prevent concurrent access, you need to lock the resource while it is being used with something like a ReentrantLock. If you need to guarantee in-order access, you can use the constructor ReentrantLock(boolean fair) with fair set to true. Otherwise, you can use a basic ReentractLock or the synchronized property.
I found a neat way with Semaphore:
class PublishService {
private static final Semaphore lock = new Semaphore(1);
public void throttleLongRunningPublish() {
try {
lock.tryAcquire(2, TimeUnit.MINUTES);
longRunningPublish();
} finally {
lock.release();
}
}
}
Related
This question already has answers here:
Java Wait and Notify: IllegalMonitorStateException
(2 answers)
Closed 4 years ago.
Was trying to practice producer and consumer using a simple counter in java.
Not sure why I am getting a Illegal Monitor State exception on this piece of code.
I have counter rest and counter consume methods which run in their own thread.
The counter itself is a static int volatile field .
The counter class also gives you a lock to
If I change the wait naotify to the following:
Counter.lock.notify();
Counter.lock.wait();
The code works. Dosen't wait() and notify() automatically takes the reference of the lock synchronize is on?
Producer Class
package multithreading;
public class CounterProducer implements Runnable {
public void run() {
try { incrCounter(); } catch (InterruptedException e) { e.printStackTrace(); }
}
public void incrCounter() throws InterruptedException {
while (true) {
synchronized (Counter.lock) {
if (Counter.counter < 1) {
System.out.println("Counter Reset");
Counter.counter = 10;
notify();
wait();
}
}
}
}
}
Consumer Class
package multithreading;
public class CounterConsumer implements Runnable {
public void run() {
try { consumeCounter(); } catch (InterruptedException e) { e.printStackTrace(); }
}
public void consumeCounter() throws InterruptedException {
while (true) {
synchronized (Counter.lock) {
if (Counter.counter > 0) {
System.out.println("Consumed");
Counter.counter--;
notify();
wait();
}
}
}
}
}
The Counter
public class Counter {
public static volatile int counter;
public static final Object lock = new Object();
}
The Counter
public class CounterRunner {
public static void main(String[] args) {
Thread con = new Thread(new CounterConsumer());
Thread prod = new Thread(new CounterProducer());
con.start();
prod.start();
}
}
The Runner
public class CounterRunner {
public static void main(String[] args) {
Thread con = new Thread(new CounterConsumer());
Thread prod = new Thread(new CounterProducer());
con.start();
prod.start();
}
}
If I change the wait naotify to the following, the code works:
Counter.lock.notify();
Counter.lock.wait();
Every Java method is either a static method of some class or an instance method of some object. If you see a method call that does not contain an explicit class name or object reference, then it is an implicit call to a method belonging to the this object.
That is to say, notify() means the same thing as this.notify(), and wait() means this.wait().
this, refers to the CounterProducer instance when it appears in your CounterProducer.incrCounter() method, and it refers to the CounterConsumer instance when it appears in your CounterConsumer.consumeCounter() method.
I'm trying to write a program that in the Main class one can initiate unknown amount of new threads.
Each thread in turn should call to a Singleton Copier class which should call a file transfer action.
My goal is, regardless the amount of threads requests, is to limit the number of concurrent transfers to 2 transfers, so I thought solving it with Semaphore.
My problem is, it's seems the threads are running one after the other and not in concurrent.
Here is what I tried to do:
public class Copier {
private static final int POOL_SIZE = 2;
private static volatile Copier instance = null;
private static Semaphore semaphore;
private Copier() {
}
public static Copier getInstance() {
if (instance == null) {
synchronized (Copier.class) {
if (instance == null) {
instance = new Copier();
semaphore = new Semaphore(POOL_SIZE);
}
}
}
return instance;
}
public void fileTransfer(CopyThread copyThread) {
try {
semaphore.acquire();
System.out.println("Running thread...");
copyThread.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
semaphore.release();
System.out.println("Thread released..");
}
}
}
This is my Main class:
public class Driver {
public static void main(String[] args) {
Copier copier = Copier.getInstance();
CopyThread copyThread1 = new CopyThread();
CopyThread copyThread2 = new CopyThread();
copier.fileTransfer(copyThread1);
copier.fileTransfer(copyThread2);
}
}
When running it - you can see by the output the threads running one after the other, while my purpose is to have up to 2 concurrent threads.
What did I do wrong?
Running thread...
3.998784MB were transferred in 5.902514932 seconds
Thread released..
Running thread...
4.062673MB were transferred in 7.199550077 seconds
Thread released..
You are supposed to call start() instead of run() otherwise it won't start your threads such that the transfer will be done sequentially which is actually the root cause of your current issue.
Anyway, for me your code should be rewritten as the class Copier should not even start() the threads as it is not its duty.
1. Rewrite the method fileTransfer()
public void fileTransfer() {
try {
semaphore.acquire();
System.out.println("Running transfer...");
// Code that performs the transfer
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
System.out.println("Thread released..");
}
}
2. Implement the method run() of CopyThread properly
#Override
public void run() {
// Here I call fileTransfer() on Copier instead of the other way around
Copier.getInstance().fileTransfer();
}
3. Make semaphore non static and final
private final Semaphore semaphore;
private Copier() {
this.semaphore = new Semaphore(POOL_SIZE);
}
4. Use an inner class to lazy create your instance
public class Copier {
...
public static Copier getInstance() {
return Holder.instance;
}
...
private static class Holder {
private static final Copier instance = new Copier();
}
}
5. Rewrite your main method
public static void main(String[] args) throws Exception {
CopyThread copyThread1 = new CopyThread();
CopyThread copyThread2 = new CopyThread();
copyThread1.start();
copyThread2.start();
}
Output:
Running transfer...
Running transfer...
Thread released..
Thread released..
If you call Thread.run() you do not start the thread, you just execute the method sequentially. You need to call start(). (I am assuming CopyThread is a Thread).
Java Puzzlers by Joshua Bloch has a chapter with a very similar example.
Is there a way to enforce only a single execution of a thread object?
Something like a thread singleton?
To illustrate, consider below example:
I have a runnable implemented class.
I would like that I will be able to call start() method only one time of the object.
You can put a boolean as attribute to check if the thread has already been launch
Add a static boolean field in your Runnable and check it at the start of the run method like this:
synchronized(MyRunnable.class) {
if(alreadyRan) {
return;
}
alreadyRan = true;
}
Well, with the tips of my friends here in this thread, I reached the following:
public class TestThread extends Thread {
static private TestThread _instance = null;
private TestThread() {}
public static TestThread getThread(){
if(_instance == null)
_instance = new TestThread();
return _instance;
}
#Override
public void run()
{
System.out.println("Hello");
}
}
And this is an example of using it, when calling start for the second time throws an exception:
public class Main {
public static void main(String[] args) {
try {
TestThread.getThread().start();
TestThread.getThread().start();
} catch (IllegalThreadStateException e) {
System.out.println("Error: Tried to start more than one instance of this thread!");
e.printStackTrace();
}
}
}
Your comments are welcomed.
I have a class which processes something. I'm trying to run a number of instances of this class in parallel.
However, I'm not sure if in TaskManager.startAll(), when I call r.go(), whether this would cause r to start running in its own thread, or within the main thread?
The total execution time that I'm getting seems to be very high, and despite my attempts at optimizing, nothing seems to be having any effect. Also, if I run a profiler on my project in Netbeans, it shows all the threads as sleeping. So I'd like to know if I'm doing something wrong?
This is the structure of the class:
public class TaskRunner implements Runnable {
private boolean isRunning = false;
public void run() {
while(true) {
while (! running) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
process();
}
}
public void go() {
isRunning = true;
}
public void stop() {
isRunning = false;
}
private void process() {
//Do some number crunching and processing here
}
}
Here's how these are being run / managed:
public class TaskManager {
private ArrayList<TaskRunner> runners = new ArrayList<>();
public TaskManager() {
for (int i = 0; i < 10; i++) {
TaskRunner r = new TaskRunner();
new Thread(r).start();
runners.add(r);
}
}
public void startAll() {
for (TaskRunner r : runners) {
r.go();
}
}
}
Indeed, you are not "doing it right." If you want to create a multi-threaded Java application, the place to start is with the java.util.concurrent package.
It appears from your code that you want to run ten tasks in parallel. I assume that after "number crunching and processing," you'll want to aggregate the results and do something with them in the main thread. For this, the invokeAll() method of ExecutorService works well.
First, implement Callable to do the work you show in your process() method.
final class YourTask implements Callable<YourResults> {
private final YourInput input;
YourTask(YourInput input) {
this.input = input;
}
#Override
public YourResults call()
throws Exception
{
/* Do some number crunching and processing here. */
return new YourResults(...);
}
}
Then create your tasks and run them. This would take the place of your main() method:
Collection<Callable<YourResults>> tasks = new List<>(inputs.size());
for (YourInput i : inputs)
tasks.add(new YourTask(i));
ExecutorService workers = Executors.newFixedThreadPool(10);
/* The next call blocks while the worker threads complete all tasks. */
List<Future<YourResult>> results = workers.invokeAll(tasks);
workers.shutdown();
for (Future<YourResult> f : results) {
YourResult r = f.get();
/* Do whatever it is you do with the results. */
...
}
However, I'm not sure if in TaskManager.startAll(), when I call r.go(), whether this would cause r to start running in its own thread, or within the main thread?
So my first comment is that you should make isRunning be volatile since it is being shared between threads. If the threads are not starting when it goes to true (or seem to be delayed in starting) then I suspect that's your problem. volatile provides memory synchronization between the threads so the thread that calls go() and makes a change to isRunning will be seen immediately by the thread waiting for the change.
Instead of spinning like this, I would use wait/notify:
// this synchronizes on the instance of `TaskRunner`
synchronized (this) {
// always do your wait in a while loop to protect against spurious wakeups
while (!isRunning && !Thread.currentThread().isInterrupted()) {
try {
// wait until the notify is called on this object
this.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
Then in the go() method you should do the following. stop() would be similar.
public void go() {
synchronized (this) {
isRunning = true;
this.notifyAll();
}
}
Notice that you should handle thread interrupts carefully. Test for isInterrupted() in the while running loop and re-interrupt a thread when InterruptedException is thrown is always a good pattern.
The total execution time that I'm getting seems to be very high, and despite my attempts at optimizing, nothing seems to be having any effect. Also, if I run a profiler on my project in Netbeans, it shows all the threads as sleeping.
So although the threads are mostly sleeping, they are still each looping 1000 times a second because of your Thread.sleep(1). If you increased the time sleeping (after making isRunning be volatile) they would loop less but the right mechanism is to use the wait/notify to signal the thread.
Awful solution, terrible. first I highly recommend you start reading some tutorial like [this]
Second, if threads should wait for a signal to go for some job, so why just don't you wait them!!!!!, something like this
import java.util.ArrayList;
public class TaskManager
{
//////////////////////
public volatile static Signal wait=new Signal();
//////////////////////
private ArrayList<TaskRunner> runners = new ArrayList<>();
public TaskManager()
{
for (int i = 0; i < 10; i++)
{
TaskRunner r = new TaskRunner();
new Thread(r).start();
runners.add(r);
}
try {
Thread.sleep(1000);
startAll();
Thread.sleep(1000);
pauseAll();
Thread.sleep(1000);
startAll();
Thread.sleep(1000);
haltAll();System.out.println("DONE!");
}catch(Exception ex){}
}
public void startAll()
{
synchronized(wait){
wait.setRun(true);;
wait.notifyAll();
}
}
public void pauseAll(){
wait.setRun(false);
}
public void haltAll(){
for(TaskRunner tx:runners){tx.halt();}
}
public static void main(String[] args) {
new TaskManager();
}
}
class TaskRunner implements Runnable
{
private Thread thisThread;
private volatile boolean run=true;
public void run()
{
thisThread=Thread.currentThread();
while(run){
if(!TaskManager.wait.isRun()){
synchronized(TaskManager.wait)
{
if(!TaskManager.wait.isRun()){
System.out.println("Wait!...");
try
{
TaskManager.wait.wait();
}
catch (Exception e)
{
e.printStackTrace();
break;
}
}
}}
process();
}
}
private double r=Math.random();
private void process(){System.out.println(r);try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}}
public void halt(){run=false;thisThread.interrupt();}
}
class Signal{
private boolean run=false;
public boolean isRun() {
return run;
}
public void setRun(boolean run) {
this.run = run;
}
}
in above sample, all runners works till the Signal run boolean is true, and simple TaskManager class set tit as false for every time it needs to pause the threads. and about the halt, it just set the shutdown(run) flag to false, and also interrupt the thread because of if thread is in wait state.
I hope I could prove your solution is like dream-on story, and also could explained enough about my solution.
have a good parallel application :)
I have some code that I want to have some one time initialisation performed. But this code doesn't have a definite lifecycle, so my logic can be potentially invoked by multiple threads before my initialisation is done. So, I want to basically ensure that my logic code "waits" until initialisation is done.
This is my first cut.
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
synchronized(initialised) {
initStuff();
initialised.getAndSet(true);
initialised.notifyAll();
}
}
public void doStuff() {
synchronized(initialised) {
if (!initialised.get()) {
try {
initialised.wait();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
}
}
doOtherStuff();
}
}
I basically want to make sure this is going to do what I think it's going to do -- block doStuff until the initialised is true, and that I'm not missing a race condition where doStuff might get stuck on a Object.wait() that will never arrive.
Edit:
I have no control over the threads. And I want to be able to control when all of the initialisation is done, which is why doStuff() can't call initialise().
I used an AtomicBoolean as it was a combination of a value holder, and an object I could synchronize. I could have also simply had a "public static final Object lock = new Object();" and a simple boolean flag. AtomicBoolean conveniently gave me both. A Boolean can not be modified.
The CountDownLatch is exactly what I was looking for. I also considered using a Sempahore with 0 permits. But the CountDownLatch is perfect for just this task.
That's a strange mix of library and built-in concurrency controls. Something like this is much cleaner:
public class MyClass {
private static final CountDownLatch latch = new CountDownLatch(1);
public void initialise() {
initStuff();
latch.countDown();
}
public void doStuff() {
try {
latch.await();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
doOtherStuff();
}
}
A synchronized block will automatically block other threads. Just use a simple lock object + status variable:
public class MyClass {
private static boolean initialised;
private static final Object lockObject = new Object();
public void initialise() {
synchronized (lockObject) {
if (!initialised) {
initStuff();
initialised = true;
}
}
}
public void doStuff() {
initialise();
doOtherStuff();
}
}
The best may be to use a static initializer (as mentioned by SB):
public class MyClass {
public static void doInitialize() {
...
}
public void doStuff() {
doOtherStuff();
}
static {
doInitialize();
}
}
This will get executed once before any other code is allowed to be called. If you will always have to initialize anytime the class is used then there is no performance hit as the class will not be loaded until it is used. See the answers to this question for more details.
It this is right at startup, why not wait to start the other threads until the initialization is complete?
Also, you can do a thread-synchronized IsComplete boolean that is set to false until it is set to true by the initialization routine.
You're using AtomicBoolean always from inside a synchronized block. There's not much point to that since only one thread can access it. Atomic variables are intended for use in lock-free solutions - you can get and set the value as an uninterruptable unit.
I guess you are looking for a lock free solution once the intiialization has happened:
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
if (!intialized.get())
{
synchornized (this)
{
if (!initialized.getAndSet(true))
doInitialize();
}
}
}
public void doStuff() {
initialize();
doOtherStuff();
}
You could also do this with a simple volatile boolean which is actually a little more efficient than an AtomicBoolean.