This is not my actual code, but it shows what I want to do. Why does the Print method end up printing the original value instead of the updated one when run inside another method? When I run them both from PSVM, it prints the number 3 like I expected it to.
public int testOne = 0;
public static void main(String[] args) {
Main tester = new Main();
tester.Increase();
}
public void Increase() {
Main tester = new Main();
testOne = 3;
tester.Print();
}
public void Print() {
System.out.println(testOne);
}
}
Output seems to come out as 0, anyone know why this happens? Running it in repl.it if it is a compiler thing.
public void Increase() {
Main tester = new Main(); // new instance Main1, testOne = 0
testOne = 3; // current instance Main0, testOne = 3
tester.Print(); // calling Main1.Print() prints 0
}
The testOne assignment you do is the one in the current class, but you're actually calling the Print() function from a completely new instance of the class you created in the local scope.
What you want to do is this:
public void Increase() {
testOne = 3;
Print();
}
This Print() method will be called from the current class context.
The problem you're facing is scope. Read up on it here: https://www.geeksforgeeks.org/variable-scope-in-java/
You have two instances of your class, so therefore two testOne variables, but you're only printing one of them
Either you need to set the instance variable
public static void main(String[] args) {
Main tester = new Main();
tester.Increase();
// tester.Print(); // would print 0
}
public void Increase() {
Main tester = new Main();
tester.testOne = 3;
tester.Print();
}
public void Print() {
System.out.println(testOne); // prints 3
}
Or don't make another instance at all
public static void main(String[] args) {
Main tester = new Main();
tester.Increase();
}
public void Increase() {
this.testOne = 3;
this.Print();
}
public void Print() {
System.out.println(testOne);
}
Another approach can be using Static.
public static int testOne = 0;
public static void main(String[] args) {
Main tester = new Main();
tester.Increase();
}
public void Increase() {
Main tester = new Main();
testOne = 3;
tester.Print();
}
public void Print() {
System.out.println(testOne);
}
Related
I have two classes that I'm trying to manipulate one variable with, as an example
public class A {
public static void main(String[] args) {
while(game_over[0] == false) {
System.out.println("in the while-loop");
}
System.out.println("out of the while-loop");
}
static boolean[] game_over = {false};
}
and
public class B {
public boolean[] game_over;
public printBoard(boolean[] game_over) {
this.game_over = game_over;
}
public void run() {
for (int i = 0; i < 10; i++) {
// do something
}
game_over[0] = true;
System.out.println("GAME OVER");
}
}
The code snippets provided are not meant to be actual workable code, I'm more concerned with the concept. In my program, class A creates a thread that utilizes class B, and I want class B to affect the variable 'game_over' such that the while-loop in class A will be affected by the change... any idea how I can successfully update the variable? Thanks.
Don't use an array for this, that makes it harder to ensure a data-race free application.
Since you want to be able to pass around the game_over flag as an independent object, the easiest way to achieve a correct multi-threaded application is to use the AtomicBoolean class.
import java.util.concurrent.atomic.AtomicBoolean;
class B {
private AtomicBoolean game_over;
public B(AtomicBoolean game_over) {
this.game_over = game_over;
}
public void run() {
// do stuff
game_over.set(true);
}
}
and in your class A:
public class A {
static AtomicBoolean game_over = new AtomicBoolean();
public static void main(String[] args) {
B b = new B();
Thread t = new Thread(b);
t.start();
while (!game_over.get()) {
System.out.println("in the while-loop");
}
System.out.println("out of the while-loop");
}
}
I have written my program around the main MonopolyGame.java game class - however - I am adding features such as splash screens etc; and I would like to call each of these from a separate class (RunFile.java) . How do I rewrite the following part of my main class so that it can be called from the RunFile.java. When I try to do this I get the following error:
The method MonopolyGame() is undefined for the type MonopolyGame
MonopolyGame.java
public class MonopolyGame extends JFrame{
// PRIVATE STATIC/DECLARATIONS ARE HERE
public static void main(String[] args) throws Exception {
{
//THIS IS WHERE I USED TO CALL THE SPLASH SCREEN
// SplashScreen s = new SplashScreen(8000);
// s.Splash();
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MonopolyGame window = new MonopolyGame();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}}
/**
* Create the application.
*/
public MonopolyGame()
{
try {
initialize();
for(int i = 0; i < 41 ; i++)
{
properties[i]=new Props();
}
setProperties();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public void initialize() throws InterruptedException {
//REST OF PROGRAM
RunFile.java
public class RunFile{
public static void main(String[] args)
{
SplashScreen s = new SplashScreen(8000);
s.Splash();
MonopolyGame m = new MonopolyGame();
m.MonopolyGame();
}
}
All you need to do is remove m.MonopolyGame(). Since it has the same name as the class, it is a Constructor and so when you do MonopolyGame m = new MonopolyGame(); it is running the logic inside of there so you don't need to do it again.
If you do want to call it separately, you should change the name of the method to something besides the classname (and add a return type such as void)
You don't need to rewrite the MonopolyGame() class, you can simply reflect the MonopolyGame() main method in your RunFile class.
public class RunFile {
public static void main(String[] args) {
Class<?> aClass = Class.forName(MonopolyGame.class.getName());
Method meth = aClass.getMethod("main", String[].class);
meth.invoke(null, (Object) args);
}
}
I have a static variable which I would like to set in a run() method. I have the following:
public class Test{
public static int temp;
public static void main(String [] args)
{
update();
System.out.println("This is the content of temp"+temp);
}
public static void update()
{
(new Thread() {
#Override
public void run() {
// do some stuff
Test.temp=15;
}}).start();
}
I would like the content of temp to be updated to 15; but when I print it in the main function, it shows 0. How can this be fixed?
Threads working concurrently so you should wait until your new thread finishes:
public class Test{
public static int temp;
public static void main(String [] args) {
update().join(); //we wait until new thread finishes
System.out.println("This is the content of temp"+temp);
}
public static Thread update() {
Thread t = new Thread() {
#Override
public void run() {
// do some stuff
Test.temp=15;
}
};
t.start();
return t;
}
You have to understand how Thread works.
I will show you two pieces of code here first is to understand, variables that are initialized inside the thread takes take time to update until the thread is finished.
public class Num {
public static int temp;
public static void main(String [] args) throws InterruptedException
{
update();
System.out.println("This is the content of temp"+Num.temp);//This will print before temp=15 is updated
}
public static void update()
{
(new Thread() {
#Override
public void run() {
// do some stuff
Num.temp=15;
System.out.println("Value of temp:"+Num.temp);//This statement prints after
}}).start();
}
}
It Prints the following:
This is the content of temp0
Value of temp:15
Second one shows, if you wait for a small amount time(Thread.sleep(10)) after the thread is executed, the value gets updated:
public class Num {
public static int temp;
public static void main(String [] args) throws InterruptedException
{
update();
Thread.sleep(10);
System.out.println("This is the content of temp"+Num.temp);//This will print correct value now
}
public static void update()
{
(new Thread() {
#Override
public void run() {
// do some stuff
Num.temp=15;
}}).start();
}
}
But here I would suggest the same method as Philip did. Just add throws InterruptedException in main function
I have a class, such as:
public class Test {
private static Thread aThread;
private static Loopy aLoop;
public Test() {
}
public static void main(String[] args) {
startUpdate();
stopUpdate();
startUpdate();
}
public static void startUpdate() {
aLoop = new Loopy();
aThread = new Thread(aLoop);
aThread.start();
}
public static void stopUpdate() {
if (aThread != null) {
aLoop.finish();
}
}
}
with runnable code that looks like:
public class Loopy implements Runnable {
private static String status = "R"; // Run
public void run() {
while (status.equals("R")) {
// Do Stuff
}
}
public void finish() {
status = "F"; // End Run
}
}
Calling startUpdate works the first time.
StopUpdate works as planned.
Calling startUpdate the second time results in no work being done as status is still equal to "F" from the stop, even though I am starting a new instance of Loopy which (to me) should have the default value of "R".
Is the status persisting across instances, or have I made an error I haven't spotted yet?
You have overused static.
In your Loopy class the String status is static and is therefore shared across all Loopy instances.
You should make status an instance variable by removing the static.
Another note is that status should also be volatile as it's state is changed by numerous threads without synchronization.
I would also suggest that maybe you should make all the variables/methods in Test instance too (except main) as it's generally best to avoid static where possible:
public class Test {
private Thread aThread;
private Loopy aLoop;
public static void main(String[] args) {
final Test test = new Test();
test.startUpdate();
test.stopUpdate();
test.startUpdate();
}
public void startUpdate() {
aLoop = new Loopy();
aThread = new Thread(aLoop);
aThread.start();
}
public void stopUpdate() {
if (aThread != null) {
aLoop.finish();
}
}
}
I think status shoud not be static
I have a class like this , where I am updating a static variable in a thread. And I need to access this variable from another class.
import java.util.ArrayList;
import java.util.List;
public class VariableUpdater implements Runnable {
static List < String > abc = new ArrayList < String > ();
private static VariableUpdater instance = null;
private VariableUpdater() {}
public static synchronized VariableUpdater getInstance() {
if (instance == null) {
instance = new VariableUpdater();
}
return instance;
}
public static void main(String[] args) {
Thread th = new Thread( VariableUpdater.getInstance());
th.start();
}
#Override
public void run() {
while (true) {
System.out.println();
try {
abc.add("aa");
Thread.sleep(1000);
printContent();
} catch (Exception e) {
// TODO: handle exception
}
}
}
public synchronized void printContent() {
for (String string: abc) {
System.out.println(string);
}
}
}
And this variable needs to be accessed from another class like this :
public class Accessor {
public static void main(String[] args) {
VariableUpdater.getInstance().printContent();
}
}
The problem is, when running the Accessor class the list is empty.
Am I missing something here?
UPDATE/Solution
It turns out we can achieve this by using Hazelcast or some sort of messaging/caching utility. I will post a full solution soon.
Source: How to share object between java applications?
From this code u can access the List in another class object
import java.util.ArrayList;
import java.util.List;
public class VariableUpdater implements Runnable {
static List < String > abc = new ArrayList < String > ();
private static VariableUpdater instance = null;
private VariableUpdater() {}
public static synchronized VariableUpdater getInstance() {
if (instance == null) {
instance = new VariableUpdater();
}
return instance;
}
public static void main(String[] args) {
Thread th = new Thread(new VariableUpdater());
th.start();
Accessor.print();
}
#Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println();
try {
abc.add("aa");
// Thread.sleep(1000);
//printContent();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public synchronized void printContent() {
System.out.println("List :: " + abc);
}
}
class Accessor {
public static void print() {
System.out.println("Accessor");
VariableUpdater.getInstance().printContent();
}
}
You have two main() methods in two different classes. On running two main() methods there will be two instances of JVM and those do not share anything. So your list will always be empty.
Use one main() method to start threads.
public class Main{
//shared state
public static void main(String[] args){
VariableUpdator variableUpdatorInstance = ...
Accessor accessorInstance = ...
variableUpdatorInstance.start();
accessorInstance.start();
//or in your case
new Thread(new VariableUpdater()).start();
Thread.sleep(9000); //runs eventually after 9 seconds
Accessor.print();
}
}
UPDATE:
class Thread1 extends Thread{
static List<String> list = new ArrayList<String>();
}
class OtherClass{
public void someMethod(){
Thread1.list; //this is how you access static variable of one class in other
}
}