Confused about instance initialization - java

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

Related

Synchronization of methods of differents classes

I have two classes each with one method.
class A {
private void insert(String usedId){
// ...
}
}
class B {
private void refresh(String userId){
// ...
}
}
Each method is called from a different Thread. They are called from different Threads for different userIds.
I need to lock the first method when second is called and vise versa for the same userId.
Is the best choice to hold a List of ids and set the lock?
We introduce a LockDispenser. You pass this object to all As and Bs you want to have thread safe. It will provide Lock objects with createLock(String forId) which need to be released after use by calling releaseLock(String forId).
public class LockDispenser {
private final Map<String, Lock> dispenser = new LinkedHashMap<>();
public Object createLock(String forId) {
synchronized (dispenser) {
if (!dispenser.containsKey(forId)) {
dispenser.put(forId, new Lock());
}
Lock lock = dispenser.get(forId);
lock.referenceCounter++;
return lock;
}
}
public void releaseLock(String forId) {
synchronized (dispenser) {
Lock lock = dispenser.get(forId);
lock.referenceCounter--;
if (lock.referenceCounter == 0) {
dispenser.remove(forId);
}
}
}
public static class Lock {
private int referenceCounter = 0;
}
}
Now the actual thread safety comes from using the Lock in a synchronized block.
public class A {
private LockDispenser dispenser;
public A(LockDispenser dispenser) {
this.dispenser = dispenser;
}
private void insert(String userId) {
synchronized (dispenser.createLock(userId)) {
// code
}
dispenser.releaseLock(userId); // consider putting this in a finally block
}
}
public class B {
private LockDispenser dispenser;
public B(LockDispenser dispenser) {
this.dispenser = dispenser;
}
private void refresh(String userId) {
synchronized (dispenser.createLock(userId)) {
// code
}
dispenser.releaseLock(userId); // consider putting this in a finally block
}
}
Make sure releaseLock(String forId) is called even if an Exception is thrown. You can do this by putting it into a finally block.
And create them like such:
public static void main(String... args) {
LockDispenser fooLock = new LockDispenser();
A fooA = new A(fooLock);
B fooB = new B(fooLock);
LockDispenser barLock = new LockDispenser();
A barA = new A(barLock);
B barB = new B(barLock);
}
fooA and fooB are thread safe with each other and so are barA and barB.

Affecting variables in different classes in Java

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");
}
}

JAVA: Can I enforce only one thread creation?

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.

Java - Using a static list from another class

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
}
}

Synchronize Protection Not Working for Dual Threads

Below is my stripped down java code for review. I have several subclasses, and when execParallel() is called, a new thread is launched. This thread and the default thread must both execute criticalFunction() several times via actionFunction(), but this function will only work properly for a given SubClassC connection if executed by only one process at a time.
I have used the keyword "synchronized" to guard against concurrent executions, however in practice the criticalFunction() is in fact being called by both threads at the same time.
Any idea What I am doing wrong?
public class MainClass extends GlobalLibrary {
public static SubClassA masterObj;
public MainClass() {
masterObj = new SubClassA();
}
public static class SubClassA {
public SubClassB subObj1;
public SubClassB subObj2;
public SubClassA() {
subObj1 = new SubClassB();
subObj2 = new SubClassB();
}
}
public static class SubClassB {
public SubClassC conObj;
public Thread ut = null;
public SubClassB() {
conObj = new SubClassC();
}
}
public static class SubClassC {
public TCPMasterConnection con=null;
public SubClassC() {
con = new TCPMasterConnection();
}
public synchronized Object criticalFunction(int arg) {
return otherClass.executeCritical(con, arg);
}
}
public boolean actionFunction(SubClassB subObj, int arg) {
return (subObj.conObj.criticalFunction(arg)==null);
}
public class ActionThread implements Runnable {
public SubClassB subObj;
private int icode;
public ActionThread(SubClassB arg1, int arg2) {
subObj = arg1;
icode = arg2;
}
public void run() {
for (int i=0; i<10; i++) actionFunction(subObj, icode);
}
}
public void execParallel() {
masterObj.subObj1.ut = new Thread(new ActionThread(masterObj.subObj1, 1));
masterObj.subObj1.ut.start();
actionFunction(masterObj.subObj1, 2);
actionFunction(masterObj.subObj1, 3);
actionFunction(masterObj.subObj1, 4);
actionFunction(masterObj.subObj1, 5);
actionFunction(masterObj.subObj1, 6);
}
}
If your goal is to protect the otherClass.executeCritical(con, arg) invocation, then you'll want to lock at the granularity of the otherClass instance. If the goal is to have only one thread using the "master connection" at a given time, which seems like it would be something you very much want, then you need the locking granularity to be at the instance of TCPMasterConnection. In the latter case, your code would look like this:
public Object criticalFunction(int arg) {
synchronized(con) {
return otherClass.executeCritical(con, arg);
}
}
Now if you have multithread-unsafe code in both otherClass and con (of TCPMasterConnection), you'll maybe want a lock with larger granularity. In that case, an easy thing might be to lock at the class level as described in other answers.
You are calling criticalFunction() on different instances so they are using different locks. You need to share a lock between all instances.
Try this
public Object criticalFunction(int arg) {
synchronized (SubClassC.class) {
return otherClass.executeCritical(con, arg);
}
}
Whether part of your code that you want to synchronize, make this instead:
Object lock = new Object();
public void doSomething{
synchronized(lock){
//your code
}
}
Synchronized methods only work at the instance level.

Categories