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
}
}
Related
I'm trying to create two classes that extends from Thread, I know how to create one class.
public class Main {
class Thred1 extends Thread {
public void run() {
System.out.println("I'm watching a video...");
}
}
class Thred2 extends Thread {
public void run() {
System.out.println("I'm eating...");
}
}
public static void main (String[] args) {
Thred1 t11 = new Thred1();
Thred2 t12 = new Thred2();
t11.start();
t12.start();
}
}
And got Main.java:15: error: non-static variable this cannot be referenced from a static context
Is there better way to implement my idea?
Your problem is with inner classes and not with threads , try to put all this code in the same file Main.java :
class Thred1 extends Thread {
public void run() {
System.out.println("I'm watching a video...");
}
}
class Thred2 extends Thread {
public void run() {
System.out.println("I'm eating...");
}
}
public class Main {
public static void main (String[] args) {
Thred1 t11 = new Thred1();
Thred2 t12 = new Thred2();
t11.start();
t12.start();
}
}
Another possible solution is to use static classes instead of the member inner classes used in your code :
public class Main {
static class Thred1 extends Thread {
public void run() {
System.out.println("I'm watching a video...");
}
}
static class Thred2 extends Thread {
public void run() {
System.out.println("I'm eating...");
}
}
public static void main(String[] args) {
Thred1 t11 = new Thred1();
Thred2 t12 = new Thred2();
t11.start();
t12.start();
}
}
Or simply you can use Lambda expression , Thread class have a constructor who accept a Runnable as parameter , Runnable is a functional interface so you can pass a Lambda expression as argument like that :
public class Main {
public static void main(String[] args) {
Thread t11 = new Thread(()->System.out.println("I'm watching a video..."));
Thread t12 = new Thread(()->System.out.println("I'm eating..."));
t11.start();
t12.start();
}
}
I read now book Thinking in Java, chapter about critical sections and I cannot understand an example, because I got exceptions which are not described in the book. An example looks like below:
class Pair {
private int x, y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
public Pair() {
this(0, 0);
}
public int getX() { return x; }
public int getY() { return y; }
public void incrementX() { x++; }
public void incrementY() { y++; }
public class PairValuesNotEqualException extends RuntimeException {
public PairValuesNotEqualException() {
super("Values are not equal: " + Pair.this);
}
}
public void checkState() {
if (x != y) {
throw new PairValuesNotEqualException();
}
}
}
abstract class PairManager {
AtomicInteger checkCounter = new AtomicInteger(0);
protected Pair p = new Pair();
public synchronized Pair getPair() {
// Make copies to protect the original
return new Pair(p.getX(), p.getY());
}
public abstract void increment();
}
// synchronization of the whole method
class PairManager1 extends PairManager {
#Override
public synchronized void increment() {
p.incrementX();
p.incrementY();
}
}
// Critical section
class PairManager2 extends PairManager {
#Override
public void increment() {
synchronized (this) {
p.incrementX();
p.incrementY();
}
}
}
class PairManipulator implements Runnable {
private PairManager pairManager;
public PairManipulator(PairManager pairManager) {
this.pairManager = pairManager;
}
#Override
public void run() {
while (true)
pairManager.increment();
}
}
class PairChecker implements Runnable {
private PairManager pairManager;
public PairChecker(PairManager pairManager) {
this.pairManager = pairManager;
}
#Override
public void run() {
while (true) {
pairManager.checkCounter.incrementAndGet();
pairManager.getPair().checkState();
}
}
}
public class CriticalSection {
static void testApproaches(PairManager pman1, PairManager pman2) {
ExecutorService exec = Executors.newCachedThreadPool();
PairManipulator
pm1 = new PairManipulator(pman1),
pm2 = new PairManipulator(pman2);
PairChecker
pcheck1 = new PairChecker(pman1),
pcheck2 = new PairChecker(pman2);
exec.execute(pm1);
exec.execute(pm2);
exec.execute(pcheck1);
exec.execute(pcheck2);
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
System.out.println("InterruptedException");
}
System.out.println("pm1: " + pm1 + "\npm2: " + pm2);
System.exit(0);
}
public static void main(String[] args) {
PairManager
pman1 = new PairManager1(),
pman2 = new PairManager2();
testApproaches(pman1, pman2);
}
}
An example output:
pm1: Pair: Pair{x=364, y=364} counter = 471421
pm2: Pair: Pair{x=365, y=365} counter = 1015604598
This example executed without exception.
In above example I understand how does it work but the problem is in example with explicit locks.
Example with explicit lock from book:
class ExplicitPairManager1 extends PairManager {
private Lock lock = new ReentrantLock();
// why synchronized ??
public synchronized void increment() {
lock.lock();
try {
p.incrementX();
p.incrementY();
} finally {
lock.unlock();
}
}
}
class ExplicitPairManager2 extends PairManager {
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
p.incrementX();
p.incrementY();
} finally {
lock.unlock();
}
}
}
public class ExplicitCriticalSection {
public static void main(String[] args) throws Exception {
PairManager
pm1 = new ExplicitPairManager1(),
pm2 = new ExplicitPairManager2();
CriticalSection.testApproaches(pm1, pm2);
}
}
Output:
Exception in thread "pool-1-thread-4" critical.sections.Pair$PairValuesNotEqualException: Values are not equal: Pair{x=2, y=1}
at critical.sections.Pair.checkState(CriticalSection.java:49)
at critical.sections.PairChecker.run(CriticalSection.java:133)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
pm1: Pair: Pair{x=1024, y=1024} counter = 3
pm2: Pair: Pair{x=1025, y=1025} counter = 1499445
First what I don't understand why author use synchronized in ExplicitPairManager1#increment if he use also Lock object? Is that the mistake in the book?
Second problem is that I don't understand why I got exception?
Excpetion was thrown in:
class PairChecker implements Runnable {
private PairManager pairManager;
public PairChecker(PairManager pairManager) {
this.pairManager = pairManager;
}
#Override
public void run() {
while (true) {
pairManager.checkCounter.incrementAndGet();
pairManager.getPair().checkState(); // here was thrown an exception
}
}
}
Why I got excpetions and author dont? Is that possible JVM behavior is different on different systems? I use Ubuntu 16.04 LTS and Java 8.
You need to synchronize on the same object if you want to establish a critical section for multiple threads.
Your exception is getting thrown for pair modified in ExplicitPairManager2.
Let's see how possible exception-causing flow looks like:
ExplicitPairManager2.lock.lock() gets acquired
ExplicitPairManager2.p.incrementX() happens
PairChecker calls getPair()
PairChecker acquires pairManager's internal (this) monitor, but it is different than ExplicitPairManager2.lock
the result of getPair() therefore has x != y
so in the end there is no critical section.
In other words, while modifying, you were using two different objects to synchronize:
ExplicitPairManager2.lock to write
internal monitor of ExplicitPairManager2 (this) to create a copy for checking state
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);
}
}
My problem concern thread. i want to get var(class variable) from method run but can't get and
i don't know what happed.
import java.util.ArrayList;
public class Interpreter_controller extends Thread{
ArrayList<String> var;
public Interpreter_controller(ArrayList<String> var) {
this.var = var;
System.out.println(this.var.isEmpty());
}
public void run() {
System.out.println(this.var.isEmpty());
}
}
when i start thread from
Interpreter_controller control = new Interpreter_controller(array_list_variable);
control.start();
Output is
false
true
What should I do to get var from run method?
New Edit
I delete extends Thread then result is correct but i want to use thread in this class
My goal is pass arraylist from another class to use in thread class(run method)
Hi Following will give you head start. Make sure list is synchronized.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class Main {
public static void main(String[] args) throws InterruptedException {
Main m = new Main();
m.execute();
}
public void execute() throws InterruptedException {
List<String> list = new ArrayList<String>();
list = Collections.synchronizedList(list);
List<Thread> tlist = new ArrayList<Thread>();
for (int i = 0; i < 5; i++) {
Thread t = new SomeThread(list, i);
t.start();
tlist.add(t);
}
while (true) {
int j = 0;
for (int i = 0; i < tlist.size(); i++) {
Thread.sleep(100);
if (!tlist.get(i).isAlive()) {
j++;
for (String s : list) {
System.out.println(s);
}
}
}
if (j == tlist.size()) {
break;
}
}
}
public class SomeThread extends Thread {
private List<String> list;
private int number;
private long sleepTime;
public SomeThread(List list, int number) {
this.list = list;
this.number = number;
sleepTime = new Random(number).nextInt(500);
}
#Override
public void run() {
try {
Thread.sleep(sleepTime);
list.add(number + " wake up from sleep");
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
My goal is pass arraylist from another class to use in thread
class(run method)
Take a look at this:
class Tmp implements Runnable {
public Object runArg;
public Tmp(Object arg) {
runArg = arg;
}
public void run() {
// thread job
}
}
Use:
new Thread(new Tmp("Hello World")).start();
So you have to create a new class rather than using anonymous class.
NOTE: Unless you are using J2ME, you should NOT use native Thread. Many problems would occur with you. You should use ExecutorService by using Executors classes:
private final ExecutorService pool = Executors.newCashedThreadPool();
...
pool.submit(new Tmp("HelloWorld"));