I have a method which is invoked by multiple threads.
public void notifyCompleted(PlayerDTO winner, PlayerDTO loser) {
PlayerRankedData winnerData = rankedDataMap.get(winner.getId());
PlayerRankedData loserData = rankedDataMap.get(loser.getId());
int pointsToAdd = getPointsToAdd(winnerData, loserData);
int pointsToDeduct = getPointsToDeduct(loserData, winnerData);
winnerData.addMatchPoints(pointsToAdd);
loserData.deductMatchPointsUptoMinimum(pointsToDeduct, minimumMatchPoints);
winnerData.addRewardTokens(tokenPerVictory);
}
And I have another method which is accessed by a scheduler, and runs only once in a month i.e. It resets the monthly ranked data for players.
private void resetLadder() {
for (PlayerRankedData playerRankedData : rankedDataMap.values()) {
int monthlyTokens = playerRankedData.getRewardTokens() * calculateTierMultiplier(playerRankedData);
playerRankedData.setUnlockedTokens(monthlyTokens);
playerRankedData.resetMonthlyDataData(); //This updates reward tokens, matchPoints and other variables which are modified inside notifyCompleted.
updateOnDatabase(playerRankedData);
}
}
What I want is that when resetLadder is running, notifyCompleted waits until resetLadder finishes its execution.
I can make it work by using a lock object and locking the body of notifyCompleted and resetLadder but I don't want to do that because then only 1 thread will be able to access notifyCompleted at a time which I don't want. Its completely fine for multiple threads to access notifyCompleted.
I think busy waiting with an AtomicBoolean can kind of make it work but issue is that if notifyCompleted is running and resetLadder starts running then it will lead to inconsistent state.
So my question is, is there a way to make notifyCompleted to run but only be blocked when resetLadder is running and resetLadder to not start when notifyCompleted is not running.
Related
Suppose I have a piece of code in Java that I want to be executed synchronously, however when the thread that owns the lock releases that lock, I do not want waiting threads to execute the synchronized code any more. I just want them to wait until the synchronized code has finished running.
So, when thread 1 enters the synchronized code (method, code block) it must get a lock on that code. Any subsequent threads must then wait for the first thread to finish running the code. So far, regular code synchronization.
However in my case, when the first thread is finished, and releases the lock, I want the waiting threads to skip that synchronized piece of code (the code updates a resource that is used by all threads).
How would I go about creating this in Java using the synchronization features? Currently I am not using the sync features, instead I am using a concurrent collection holding the lock (context), like herebelow. However, the process of locking still needs to be synchronized somehow, because two threads are able to get a lock on the context.
Cheers!
Kjeld
/*
* A concurrently accessible set of contexts.
*/
private static final Set<String> LOCKED_CONTEXTS;
static {
LOCKED_CONTEXTS = ConcurrentHashMap.newKeySet(); // meanwhile, I replaced this with Collections.synchronizedSet(new HashSet<>())
}
...
if (!LOCKED_CONTEXTS.contains(context)) {
LOCKED_CONTEXTS.add(context);
log.debug("Locked context: {}", context);
try {
doTask();
} finally {
LOCKED_CONTEXTS.remove(context);
log.debug("Released context: {}", context);
}
} else {
log.debug("Waiting for context to be released: {}", context);
while (LOCKED_CONTEXTS.contains(context)) {
}
log.debug("The waiting is over, context is released: {}", context);
}
I think you want to combine a lock with a semaphore.
tryLock on the lock
if you got it, do work. At the end of the work, mark the semaphore as complete
if you did not get it, wait for the semaphore to complete
Maybe I don't fully understand your use-case, but from what I get you want a piece of code to only run once for all triggers during its execution, but again if any trigger happens outside of the previous execution window.
Does this cover it?
class Work {
private volatile boolean done;
void queueWorkOnce() {
done = false;
actualWork();
}
private synchronized void actualWork() {
if (!done) {
//TODO: do work
done = true;
}
}
}
I have a socket server that uses an ExecutorService to create a new thread for each new socket. I also have a static instance of a class that makes database calls that all threads use.
My server is used for online chess matches. When a user makes a move, the move is sent to the server and an entry is made in the DB with general information about the move (including the ID of the match). Every 10 seconds or so, if the match's other client also has an active socket to the server, it will ask the server to fetch all new data about the match.
It works, but as you can imagine gets pretty inefficient if a non-trivial number of players are connected. What I want is a way for a thread to peek into the thread pool and find another thread based off an ID (The ID of the client for whom the thread is used), then call a method on that thread to send a message to the opposing player.
I've been looking all over, and I've had no luck. Is such a thing possible? If it is, is it advisable? Even if it's a bit risky code-wise, I'm willing to take extra steps to mitigate the risk for the enormous resource-saving benefits.
Like I said in my comment, your question is confusing; if all you're trying to do is to notify the opponent when a player makes a move, the simplest implementation is to use a BlockingQueue. The Javadoc even has code examples, so it should be fairly easy to implement. In your case, whenever a player makes a move, you put an item in the queue, that the consumer picks up and notifies the opponent that is participating in the same game. You don't need to mess with low level thread constructs, and if you're even thinking of finding threads based on ids from a pool, you're doing it all wrong.
The BlockingQueue would work, but it involves busy wait, so I'm not a big fan of it. Instead, you can use the Observer design pattern; the JDK already has support for this. Following is an example that I made up:
public class Main extends Observable implements Observer {
private final int numCores = Runtime.getRuntime().availableProcessors();
private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);
public Main() {
addObserver(this);
}
public static void main(String[] args) throws InterruptedException {
new Main().execute();
}
private void execute() {
for (int i = 0; i < 5; ++i) {
this.setChanged();
this.notifyObservers(i);
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
#Override
public void update(Observable o, Object arg) {
System.out.printf("Received notification on thread: %s.\n", Thread.currentThread().getName());
executor.submit(() -> System.out.printf("Running in thread: %s, result: %s.\n",
Thread.currentThread().getName(), arg));
}
}
Received notification on thread: main.
Running in thread: pool-1-thread-1, result: 0.
Received notification on thread: main.
Running in thread: pool-1-thread-2, result: 1.
Received notification on thread: main.
Running in thread: pool-1-thread-3, result: 2.
Received notification on thread: main.
Running in thread: pool-1-thread-4, result: 3.
Received notification on thread: main.
Running in thread: pool-1-thread-5, result: 4.
Last but not the least, if you really want to take it up a notch, use messaging. You didn't mention if you're using a framework (again, lack of information on your part), but Spring supports messaging, so does Akka, Play and Camel.
You may create the ExecutorService supplying your own ThreadFactory able to create your istantiate your own class that extends Thread and has a reference to the ThreadFactory itself. The ThreadFactory should trak all created Thread and be able to identify them by their ID. Such a way, each Thread will be able to query the ThreadFactory for some ID.
I currently have the following problem:
I have made a 'Cache Updater Thread', which checks for updates and then sleeps for some amount of time. I have also build a Button, which enables the user to check for updates manually. The Thread is built like this:
public static Thread cacheUpdater = new Thread(new Runnable() {
int milliSecondSleepTime = 10000;
public void run() {
try {
cacheUpdater.setPriority(Thread.MIN_PRIORITY);
//Infinite loop
while (!terminate) {
syncStatus.set(0);
//Check for updates with some methods, not important here.
syncStatus.set(1);
Thread.sleep(this.milliSecondSleepTime);
}
}
catch (InterruptedException e) {
//First check if it is termination time
if (!terminate) {
syncStatus.set(0);
this.run();
}
}
catch (Exception e) {
System.out.println(e);
}
return;
}
});
If the user clicks the manual-update button, the following code is being runned:
#FXML public void syncOnRequest() {
//Only call interrupt, because then it will start again when terminate is still false
CacheManager.cacheUpdater.interrupt();
System.out.println(CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING));
while (!CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING)) {
//LOOP FOREVER
}
//Some code that needs to be executed after the cache is updated
}
I would like to continue executing code in the syncOnRequest() method, when the cache updater is ready with its manual update. I had the idea to check if it is sleeping, but this is not working, because the System.out.println() immediately returns true. I have measured the time it takes to do the update, and its between 200 and 400 ms.
What am I doing wrong here? And why is it always returning true?
Additional question: sometimes a click on the button just kills the Thread, because it just woke up. The InterruptedException is not thrown.
How can I make sure the Thread will also restart in that case?
Note that Thread#interrupt() is the only polite way to ask your thread to interrupt itself (unless you explicitly implement another). Using it to restart the check is therefore a bad practice. So is checking the thread state for synchronization purposes and exposing the thread that keeps your cache up-to-date to external clients.
You manager should have a updateCache() method you will call directly from UI code and auto-update thread will call the same method periodically*. In that method, make sure that access to your cached data is either correctly synchronized or it happens atomically.
*) Instead of implementing your own periodic thread, consider using
Timer and TimerTask classes as well as making it a daemon thread.
Short version: WebElement.submit() is blocking; thus I can't utilize the time page being rendered to do something else.
Long version:
I'm using WebDriver Java Client Library 2.16.1
I have an automated test current done serially but can be done in parallel (basically log in to n different users to check status). Thus I'm trying use Thread to make it run concurrently: fire up multiple instances of Firefox at the same time.
The example code:
public class FirefoxRunnable implements Runnable {
#Override
public void run() {
WebDriver d = new FirefoxDriver();
d.get("http://www.facebook.com");
d.findElement(By.id("email")).sendKeys("username");
d.findElement(By.id("pass")).sendKeys("password");
d.findElement(By.id("pass")).submit();
}
}
public static void test() {
Thread t1 = new Thread(new FirefoxRunnable("Thread 1"));
Thread t2 = new Thread(new FirefoxRunnable("Thread 2"));
t1.start();
t2.start();
}
Problem: d.findElement(By.id("pass")).submit() is blocking while the page is being loaded.
Any suggestion on how to utilize the time page being loaded to do something useful?
You can not actually. Ultimately d.findElement(By.id("pass")).submit() has to be executed by CPU and if its a blocking call then it is going to utilize CPU (I am talking all this in context of single core). However modern OS will give a time slice to each thread so this is not necessary that from start to end all the time will be taken up by d.findElement(By.id("pass")).submit(). CPU will basically give your other threads and parent thread chance to execute.
Rather than submit , you can alternatively simulate Keypress "Keys.ENTER", which wont be blocking, and then you can explicit wait or find_element body tag (or any method that dont block) in ur sleep loop e.g >
for loop{
if not found() //found (e.g findElement(body)) is non blocking, make sure no implicit wait
sleep(3 secs) // while sleep utilize this time
}
How to kill the thread?
.....
How to restart them again in multi threading?
Since your post is tagged "Java," I have a good idea of what you are saying. Let's say you start a thread by doing:
Thread foo = new Thread(someRunnable);
foo.start();
Now that destroy and friends are deprecated, you need a way to kill the thread. Luckily for you, there has always been the concept of "interrupts." Simply change your runnable so that, on interrupt, it exits. Then call the thread's interrupt method.
foo.interrupt();
If you wrote your Runnable to handle this correctly, it will stop whatever it is doing and terminate.
Thread.stop() kills a thread, but you definitely don't want to do this (see the API documentation for an explanation why). Thread.interrupt() sends an asynchronous notification to a thread, so that it can shut itself gracefully.
For a comprehensive text on Java multithreading, I recommend B. Goetz, Java Concurrency in Practice, Addison-Wesley Professional.
The preferred way for a Thread to die is for the execution of the run method to go to completion:
Thread t = new Thread(new Runnable() {
public void run() {
// Do something...
// Thread will end gracefully here.
}
}
Once a thread gracefully dies in the example above, the Thread cannot be restarted. (Trying to call Thread.start on a thread that has already been started will cause an IllegalThreadStateException.)
In that case, one can make another instance of the thread and call start on that.
Probably a good place to get more information on threading would be Lesson: Concurrency from The Java Tutorials.
i wrap my worker threads up in their own class and use a terminated property to kill the thread proc loop.
sorry i dont have a java version to hand right now but you should get the idea from this
http://pastie.org/880516
using System.Threading;
namespace LoaderDemo
{
class ParserThread
{
private bool m_Terminated;
private AutoResetEvent m_Signal;
private string m_FilePath;
...
public ParserThread(AutoResetEvent signal, string filePath)
{
m_Signal = signal;
m_FilePath = filePath;
Thread thrd = new Thread(this.ThreadProc);
thrd.Start();
}
public bool Terminated {
set { m_Terminated = value; }
}
private Guid Parse(ref string s)
{
//parse the string s and return a populated Guid object
Guid g = new Guid();
// do stuff...
return g;
}
private void ThreadProc()
{
TextReader tr = null;
string line = null;
int lines = 0;
try
{
tr = new StreamReader(m_FilePath);
while ((line = tr.ReadLine()) != null)
{
if (m_Terminated) break;
Guid g = Parse(ref line);
m_GuidList.Add(g);
lines++;
}
m_Signal.Set(); //signal done
}
finally
{
tr.Close();
}
}
}
}
The best way to kill a thread is to set up a flag for the thread to watch. Program the thread to exit when it sees the flag is set to true. There's no way to restart a killed thread.
If you want to start, stop, restart threads at will, maybe using the Java 5 concurrency package would be a good idea. You can have an Executor that will do a bit of work, and when you need that bit of work to be done again, you can just re-schedule it to be done in the executor.
Regarding your first query on killing thread:
You can find more details about topic in below SE questions:
How to properly stop the Thread in Java?
How can I kill a thread? without using stop();
How to start/stop/restart a thread in Java?
Regarding your second query of re-starting thread, it's not possible in java.
You can find below details in documentation page
public void start()
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Instead of plain Threads, you can use advanced concurrent API for thread life cycle management. Have a look at this post for ExecutorService details :
How to properly use Java Executor?