Okay so I have tested this code on java 8, 11, and 14, they all have the same result.
This is bad practice and an unrealistic scenario, but I would like to understand the JVM internals that causes this to happen.
If you run this code you will notice that everything except the print part itself of system.out.println inside if execute.
At some point with a slightly different java version I managed to get it to print by changing "play" too volatile, but even that doesn't work now.
Please at least test the code before claiming it is simply deadlocking the variables or using the cache, it is not, the if executes and everything inside it works except the print part itself.
public class Main {
public static void main(String[] args) {
TestClass t = new TestClass();
System.out.println("Starting test");
new MyRunnable(t).start();
while (true)
t.testUpdate(System.currentTimeMillis());
}
}
public class MyRunnable extends Thread {
private TestClass t;
public MyRunnable(TestClass t) {
this.t = t;
}
#Override
public void run() {
try {
Thread.sleep(500L);
t.setPlay(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class TestClass {
private boolean play = false;
private long lastUpdate = 0;
private long updateRate = 2000;
private boolean hasSysoBeenHit = false;
public void testUpdate(long callTime) {
System.out.println(play);
System.out.println((callTime-lastUpdate));
if (this.play && ((callTime-lastUpdate) >= updateRate)) {
System.out.println("Updating! " + (hasSysoBeenHit = true));
this.lastUpdate = callTime;
}
System.out.println("hasbeenhit? " + hasSysoBeenHit);
}
public void setPlay(boolean t) {
System.out.println("Starting game...");
this.play = t;
}
}
Your code is suffering from a data race on the TestClass.play field: there are 2 threads accessing this field and at least one of them does a write. This is already indicated by #aerus.
If you make the field volatile, the data race gets removed. Look for the volatile variable rule in the Java Memory model.
I would also move the logic for the play checking to the begin of the testUpdate method:
public void testUpdate(long callTime) {
if(!play)return;
...
Related
I am a beginner in multi-threading and came across this example on ReadWriteLock.
ScoreBoard
public class ScoreBoard {
private boolean scoreUpdated = false;
private int score = 0;
String health = "Not Available";
final ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock();
public String getMatchHealth() {
rrwl.readLock().lock();
if (scoreUpdated) {
rrwl.readLock().unlock();
rrwl.writeLock().lock();
try {
if (scoreUpdated) {
score = fetchScore();
scoreUpdated = false;
}
rrwl.readLock().lock();
} finally {
rrwl.writeLock().unlock();
}
}
try {
if (score % 2 == 0 ){
health = "Bad Score";
} else {
health = "Good Score";
}
} finally {
rrwl.readLock().unlock();
}
return health;
}
public void updateScore() {
try {
rrwl.writeLock().lock();
//perform more task here
scoreUpdated = true;
}finally {
rrwl.writeLock().unlock();
}
}
private int fetchScore() {
Calendar calender = Calendar.getInstance();
return calender.get(Calendar.MILLISECOND);
}
}
ScoreUpdateThread
public class ScoreUpdateThread implements Runnable {
private ScoreBoard scoreBoard;
public ScoreUpdateThread(ScoreBoard scoreTable) {
this.scoreBoard = scoreTable;
}
#Override
public void run() {
for(int i= 0; i < 5; i++) {
System.out.println("Score Updated.");
scoreBoard.updateScore();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Main
public class Main {
public static void main(String[] args) {
final int threadCount = 2;
final ExecutorService exService = Executors.newFixedThreadPool(threadCount);
final ScoreBoard scoreBoard = new ScoreBoard();
exService.execute(new ScoreUpdateThread(scoreBoard));
exService.execute(new ScoreHealthThread(scoreBoard));
exService.shutdown();
}
}
Wont in the ScoreBoard while updating the health variable , we need to acquire the WriteLock since we are updating a shared variable ?
Wont in the ScoreBoard while updating the health variable , we need to acquire the WriteLock since we are updating a shared variable ?
You are correct that the class's getMatchHealth() method performs a modification of the shared health variable without holding the write lock. There being no other mechanism in the class for synchronizinging those writes, this produces a data race when two threads invoke getMatchHealth() on the same ScoreBoard without engaging some form of external synchronization. This appears to be a flaw in the method, and the method appears to have some other, more subtle synchronization issues, too.
Nevertheless, the program presented appears not ever to invoke getMatchHealth() at all, and the other ScoreBoard methods appear to be free of synchronization flaws, so the particular program presented is not affected by the flaws. Still, unless those flaws are intentional -- for didactic purposes, for instance -- I would recommend finding a better source of tutorial material than the one that provided the example program.
I don't know exactly what issue you are facing, But the issue I think is:
1) You should make scoreUpdated and health variable to public and volatile, currently it is private and default respectively.
2)When you are taking write lock in method getMatchHealth() before releasing it you are again taking read lock, which you have released just before.
I'm going to try to explain this the best I can, and hopefully you can understand my problem.
I'm designing a processor simulation program in Java, and right now I'm currently coding the "clock unit" which is going to control the program's execution. Basically, I have a class ClockUnit that changes state between 0 and 1 periodically. I need a second class Processor to be able to know when the clockunit class changes state, and then executes an instruction. So...
ClockUnit state = 0.
Processor does nothing.
ClockUnit change state = 1.
Processor executes instruction
At the moment I am running the ClockUnit class within a thread, I now need a way to run the Processor class and allow it to constantly check the state of the clock and when it changes to a 1 to execute an instruction. I'm not sure how to do this.
Do I need to create a second thread and run the Processor class from the second thread?
I hope it's clear what I need to happen. In my head its quite a simple task, I just need one thread to constantly check the state of another, but I'm not sure how to go about it.
I have posted my code below. There isn't really much complexity to it.
Main class
public class Main {
private static ALU alu;
private static ClockThread clockThread;
public static void main(String[] args)
{
//two threads, both running at the same time, one thread has clock ticking, other thread gets state of ticking clock and executes on rising edge
alu = new ALU();
clockThread = new ClockThread("clockThread", 1);
clockThread.start();
while(clockThread.getClock().getState() == 1)
{
System.out.println("ON");
}
}
}
ClockThread class
import java.util.Timer;
public class ClockThread extends Thread {
private String threadName;
private double instructionsPerSecond;
private Timer timer;
private Clock clockUnit;
public ClockThread(String name, double insPerSec)
{
threadName = name;
System.out.println("Clock thread initialised");
instructionsPerSecond = insPerSec;
}
public void run()
{
clockUnit = new Clock(instructionsPerSecond);
timer = new Timer();
timer.scheduleAtFixedRate(clockUnit, 0, (long) (clockUnit.timePeriod() * 1000));
}
public Clock getClock()
{
return clockUnit;
}
}
Clock class
import java.util.TimerTask;
public class Clock extends TimerTask{
private int state = 0; //the state of the simulation, instrutions will execute on the rising edge;
private double executionSpeed; //in Hz (instructions per second)
private String threadName = "Clock";
public Clock(double instructionsPerSecond)
{
executionSpeed = instructionsPerSecond;
System.out.println("[Clock] Execution speed set to " + executionSpeed + "Hz. (" + timePeriod() + "s per instruction.)");
}
public void run()
{
toggleState();
System.out.println("System State: " + state);
}
public void toggleState()
{
if(state == 1)
{
state = 0;
}
else if(state == 0)
{
state = 1;
}
}
public double timePeriod() //takes the number of instructions per second (hz) and returns the period T (T = 1/f);
{
double period = 1/executionSpeed;
return period;
}
public double getExecutionSpeed()
{
return executionSpeed;
}
public int getState()
{
return state;
}
}
Since you already have a reliable clock source (the producer), you can use a BlockingQueue to send 'EdgeChange' alerts to the ALU? (the unit responsible for executing instructions). The clock source will 'offer' the edge change event, and the ALU? will receive it (and subsequently do work). Here is the slight changes to your code to share events across objects in different threads:
Main:
public static void main(String[] args) {
BlockingQueue<Integer> edgeAlerts = new ArrayBlockingQueue<Integer>(2);
clockThread = new ClockThread("clockThread", 1, edgeAlerts);
clockThread.start();
boolean isInterrupted = false;
while(!isInterrupted) {
try {
Integer edgeValue = edgeAlerts.take();
if (edgeValue == 1) {
System.out.println("Executing instruction");
// Perform the instruction
}
} catch (InterruptedException e) {
isInterrupted = true;
}
}
}
You have to pass the BlockingQueue to your ClockThread ...
private final BlockingQueue<Integer> edgeAlerts;
public ClockThread(String name, double insPerSec, BlockingQueue<Integer> edgeAlerts)
{
threadName = name;
this.edgeAlerts = edgeAlerts;
System.out.println("Clock thread initialised");
instructionsPerSecond = insPerSec;
}
And to your Clock:
private final BlockingQueue<Integer> edgeAlerts;
public Clock(double instructionsPerSecond, BlockingQueue<Integer> edgeAlerts)
{
this.edgeAlerts = edgeAlerts;
executionSpeed = instructionsPerSecond;
System.out.println("[Clock] Execution speed set to " + executionSpeed + "Hz. (" + timePeriod() + "s per instruction.)");
}
And your clock run becomes:
public void run()
{
toggleState();
System.out.println("System State: " + state);
edgeAlerts.offer(state);
}
Let me know if this works for you.
I am working in a method (using spring) that will manage a lot of data and information, consulting to the database and generate some files.
I am trying to avoid a timeout exception, so, I decided I should use the #Async annotation.
Not quite sure if it works as I think or not, but I also realized that I will need the method who calls Async to wait until it is finished...so, could be the same problem, couldn't it?
Is there any way I can have a sort of listener that will read the Async information that is being processed at my bean without have to wait for all the Async process to finish??
Right now is somehow like this
private Long myFIrstMethod(){
// DO A LOT OF THINGS AND CALL TO MY ASYNC METHOD
// evaluate if the Async method will have something or not... and based on it make the return
if (myOtherMethod()){
return soemvalue;
}else{
return someOtherValue
}
#Async Future<Boolean> myOtherMethod() {
//do something
new AsyncResult<Boolean>(true); //or false...
}
}
So, I was thinking, I might get a timeout exception on myFirstMethod is there any way to handle long time processing methods and avoiding this exception?
Thanks.
You could use a Timeout
http://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/io/TimeOut.java
Set your timeout length to the length you want to wait. In the meantime, should your method return in a timely manner, you can cancel the TimeOut.
package tjacobs.io;
public class TimeOut implements Runnable {
private long mWaitTime;
private boolean mRunning = true;
private Thread mMyThread;
private TimeOutCmd mTimeOutCmd;
public static final int DEFAULT_URL_WAIT_TIME = 30 * 1000; // 30 Seconds
public static final int NO_TIMEOUT = -1;
public static final int DEFAULT_WAIT_TIME = NO_TIMEOUT;
public static interface TimeOutCmd {
public void timeOut();
}
public TimeOut(TimeOutCmd cmd) {
this(cmd, DEFAULT_WAIT_TIME);
}
public TimeOut(TimeOutCmd cmd, int timeToWait) {
mWaitTime = timeToWait;
mTimeOutCmd = cmd;
}
public void stop() {
mRunning = false;
mTimeOutCmd.timeOut();
if (mMyThread != null) mMyThread.interrupt();
}
/**
* reset the TimeOut
*
*/
public void tick() {
if (mMyThread != null)
mMyThread.interrupt();
}
public void run () {
mMyThread = Thread.currentThread();
while (true) {
try {
Thread.sleep(mWaitTime);
stop();
}
catch (InterruptedException ex) {
if (!mRunning) {
return;
}
}
}
}
}
I just got simple problem, but it seems that I cant find a solution for it. Well the following code is part of open-source project, but this part is written by me from scratch.
Well, everything inside this "script" works well without problems except of one thing,
the int variable CB_State doesn't change after calling StartParticipation() method:
import java.util.Calendar;
import java.util.logging.Logger;
import com.l2jserver.gameserver.Announcements;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
public final class CastleBattle
{
private static Logger _log = Logger.getLogger("CastleBattle");
private static String htm_path = "data/scripts/l2dc/CastleBattle/";
public static int CB_State = 1; // 0 - Disabled, 1 - Not running, 2 - Participation start, 3 - Participation end, 4 - Running, 5 - Event ended
public CastleBattle()
{
CB_Init();
}
// Initialize Engine
private static void CB_Init()
{
if (CB_State == 1)
{
SetStartTime();
}
}
// Event Loop
public static void SetStartTime()
{
Calendar _nextTime = Calendar.getInstance();
int _m = _nextTime.get(Calendar.MINUTE);
int x = 1;
while (_m > 5)
{
_m -= 5;
x++;
}
_nextTime.set(Calendar.MINUTE, x * 5);
ThreadPoolManager.getInstance().scheduleGeneral(new CastleBattleLoop(), _nextTime.getTimeInMillis() - System.currentTimeMillis());
}
// Allow players to participate in the event
public static void StartParticipation()
{
CB_State = 2;
Announcements.getInstance().announceToAll("Castle Battle participation has started.");
_log.info("Castle Battle participation has started.");
}
// Player requests to join event via NPC
public static void CB_bypass(String _cmd, L2PcInstance _player)
{
if (_cmd.startsWith("InitHtmlRequest"))
{
if (CB_State == 0)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_Disabled.htm");
_player.sendPacket(_html);
}
if (CB_State == 1)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_NotRunning.htm");
_player.sendPacket(_html);
}
if (CB_State == 2)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_Participate.htm");
_player.sendPacket(_html);
}
}
}
public static void main(String[] args)
{
_log.info("# Castle Battle Engine #");
_log.info("Author : HyperByter");
_log.info("Version : Beta");
_log.info("Version : 3.7.2013");
new CastleBattle();
}
}
class CastleBattleLoop implements Runnable
{
#Override
public void run()
{
if (CastleBattle.CB_State == 1)
{
CastleBattle.StartParticipation();
}
}
}
So any suggestions how to fix this problem?
The method StartParticipation() is probably never called:
main() calls the constructor of CastleBattle
The CastleBattle constructor calls CB_Init()
CB_Init() calls SetStartTime()
SetStartTime() invokes this line:
ThreadPoolManager.getInstance().scheduleGeneral(new CastleBattleLoop(), _nextTime.getTimeInMillis() - System.currentTimeMillis());
after some whacky and indecipherable arithmetic on _nextTime, it's likely that the schedule interval is either very large, or perhaps negative, either of which may cause the Runnable CastleBattleLoop to never be started, in which case StartParticipation() would never be called.
I don't know what ThreadPoolManager does with strange input, but I would start by debugging what value is being passed into the scheduleGeneral() method and read the javadoc to see what effect such a value would have.
The class at the bottom is called CastleBattleLoop , but it does not contain anything loopy, so StartParticipation() gets called only once (if CB_State is 1 at that moment).
You should add something like
while(running){
if (CastleBattle.CB_State == 1)
{
CastleBattle.StartParticipation();
}
Thread.sleep(100);
}
StartParticipation() is being called inside a thread.
Check if you are trying to figure out its value even before actual change occurs.
[Not sure how are you figuring out the value of "CastleBattle.CB_State" in later part of the code]
Alright, this is probably something simple, but I just can't get it.
package foo.foo.foo;
public class Vars {
public static boolean foo = false;
}
Alright, so that's my Vars class.
I then have a JFrame, with a JMenuBar,JMenu,and a JMenuItems.
items = new JCheckBoxMenuItem("Foo");
items.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
AbstractButton ab = (AbstractButton)e.getSource();
Vars.foo = ab.getModel().isSelected();
System.out.println(Vars.foo);
}
});
menu.add(items, 0);
menuBar.add(menu,0);
All is good, it returns true for the println.
Now, this is the actual problem part...
I have a if statement
if(Vars.foo)
This -should- work, right? It never executes the code inside the if brackets, UNLESS I add this line of code above it.
System.out.println(Vars.foo);
That naturally prints true, then the if statement works, but if I comment out that line, it doesn't work.
I've also been googling, and tried this:
Vars v = null;
if(v.yoo)
That still won't do it unless I have the println, I have no idea why the println makes it work. Can you explain why/how this works?
Edit:
public class painthandling implements Runnable {
#Override
public void run() {
Vars y = null;
while(true){
if(y.foo){
//some code here
}
System.out.println(y.foo);
}
}
}
That's the part that's not working, the if statement. always returns false.
frame f = new frame();
(new Thread(new painthandling())).start();
System.out.print("Got it.");
The JFrame part is called in the new frame, then the other class is called there, with the Vars class called in both. in painthandling(), the if statement returns false if it doesn't have the println.
Short answer: Make the variable volatile
Long answer:
I have done some testing, and I can actually reproduce your situation (at least I think it's the same). Consider this code:
public class Test {
public static boolean foo = false;
public static void main(String[] args) {
new Thread(new Runnable(){
#Override
public void run() {
while(true) {
try {
Thread.sleep(2000);
System.out.println("Swapping");
Test.foo = !Test.foo;
}
catch(Exception e) {
e.printStackTrace();
}
}
}
}).start();
while(true) {
if(Test.foo) {
System.out.println("I'm here");
}
}
}
}
This never prints I'm here. However, as the OP states, adding a System.out.println to the while loop does make it print it. But interestingly enough, it can be any println statement. It doesn't need to print the variable value. So this works:
public class Test {
public static boolean foo = false;
public static void main(String[] args) {
new Thread(new Runnable(){
#Override
public void run() {
while(true) {
try {
Thread.sleep(2000);
System.out.println("Swapping");
Test.foo = !Test.foo;
}
catch(Exception e) {
e.printStackTrace();
}
}
}
}).start();
while(true) {
if(Test.foo) {
System.out.println("I'm here");
}
System.out.println(""); // Doesn't have to be System.out.println(Test.foo);
// This also works (lock is just an object)
// synchronized(lock) {
// int a = 2;
// }
}
}
}
There are some other cases that also produces the "expected" output, and that is making the variable volatile, or doing a Thread.sleep() inside the while loop where the test is done. The reason it works when the System.out.println is probably because println is synchronized. And in fact, doing any synchronized operation inside the loop have the same effect. So to conclude, it's a threading (memory model) issue, and it can be resolved by marking the variable as volatile. But this does not change the fact that doing multithreaded access with a static variable is a bad idea.
I suggest reading Chapter 17 of the Java Language Specification to learn more about threads, synchronization and the Java memory model.
I didn't really read your post but after skimming it looks like you are trying to use the static method like this.
someMethod() {
Var var = null;
boolean bool = var.foo
}
The nice thing about static method and fields is that you don't have to instantiate them, try this instead:
someMethod() {
boolean bool = Var.foo
}