I am trying to access instance variable inside a Thread anonymous class . I am getting an error here saying to make it static . The point here is if i can access "this" keyword inside the anonymous class which treats it as its current object holder, then why is it not able to access the instance variables in a non static way .
public class AnonymousThreadDemo {
int num;
public AnonymousThreadDemo(int num) {
this.num = num;
}
public static void main(String[] args) {
Thread thread = new Thread() {
#Override
public void run() {
System.out.println("Anonymous " + num); // Why cant we access num instance variable
System.out.println("Anonymous " + this); // This can be accessed in a nonstatic way
}
};
thread.start();
}
}
num is a non static field, it belongs to a specific instance. You can not reference it in static main directly, because a static method can be called without creating an instance.
this is actually referencing thread, it is a local variable, when you execute run, the thread must have been created.
If you try reference AnonymousThreadDemo.this in main, you will get same result:
public static void main(String[] args) {
Thread thread = new Thread() {
#Override
public void run() {
System.out.println("Anonymous " + AnonymousThreadDemo.this); // compile error
}
};
thread.start();
}
This is ok, you can reference a local variable in local class:
public static void main(String[] args) {
int num = 0;
Thread thread = new Thread() {
#Override
public void run() {
System.out.println("Anonymous " + num);
}
};
thread.start();
}
This is ok, you can reference a non static local class field in its method:
public static void main(String[] args) {
Thread thread = new Thread() {
int num = 0;
#Override
public void run() {
System.out.println("Anonymous " + num);
}
};
thread.start();
}
Check this for more.
num is non static that means it will come after static main in the memory. Hence when main will try to point num it won't be available in the memory ie. It still won't be declared yet.
Related
I have two threads and in one thread I set static variable and in another I check static variable via function like this
Test test= new Test();
while(!Temp.isVarSet()){
}
System.out.println("Variable set");
But this codes hangs - doesn't go to println statement. But the following code works
Test test= new Test();
while(!Temp.isVarSet()){
System.out.println("I am still here");
}
System.out.println("Variable set");
The Temp class
public class Temp {
private volatile static boolean varSet=false;
public synchronized static void setVarSet() {
Temp.varSet=true;
}
public synchronized static boolean isVarSet() {
return Temp.varSet;
}
}
Test class
public class Test{
public Test() {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Model model= new Model();
View view = new View();
Controller controller=new Controller(model, view);
Temp.setVarSet();
...
}
});
}
}
What can be reason? I set method isVarSet() synchronized but it didn't help.
EDIT
This code works too.
Test test = Test()
while(!Temp.isVarSet()){
Thread.sleep(100);
}
You didn't publish what happens in Temp and isVarSet but most probably you change a variable. This variable must be marked volatile.
If your class looks like this:
public class Temp {
private static boolean someFlag;
public static boolean isVarSet() {
return someFlag;
}
}
And your loop is the same as the example, the compiler thinks that there's no need to read the flag over and over again because the flag is not changed inside the loop and it optimizes to not read the flag over and over.
Marking someFlag as volatile:
private static volatile boolean someFlag;
Will force the runtime to check the flag on each iteration and not just assume that the value hasn't changed. In this case, it will work.
From Oracle docs about atomic access:
Atomic actions cannot be interleaved, so they can be used without fear
of thread interference. However, this does not eliminate all need to
synchronize atomic actions, because memory consistency errors are
still possible. Using volatile variables reduces the risk of memory
consistency errors, because any write to a volatile variable
establishes a happens-before relationship with subsequent reads of
that same variable. This means that changes to a volatile variable are
always visible to other threads. What's more, it also means that when
a thread reads a volatile variable, it sees not just the latest change
to the volatile, but also the side effects of the code that led up the
change.
Even after you made variable as volatile .
if you add SOP in while loop it is working
These two usecase gives me another thought. just try it.
Since your read and write methods are sync , in your while loop
while(!Temp.isVarSet()){
}
It is nothing doing other than calling the method, it may possible this sync method holds the lock on the Temp Object which does not allow other thread to modify the values (though sync setMethod) .
While add SOP inside the while , it is doing some work on IO and thus it is allowing some time slice to other thread get the lock of Temp and modify the same.
Could you please try remove Sync from read method , just for testing purpose and post your results.
public class Temp {
private volatile static boolean varSet=false;
public synchronized static void setVarSet() {
Temp.varSet=true;
}
public static boolean isVarSet() {
return Temp.varSet;
}
}
This works perfect for me:
public class ThreadTest {
public static void main(String[] args) throws Exception {
Thread t1 = new TheThread();
t1.start();
// wait
Thread.sleep(500);
System.out.println(Thread.currentThread().getId() + " will now setVarSet()");
Temp.setVarSet();
System.out.println(Thread.currentThread().getId() + " setVarSet() setted");
t1.join();
System.out.println(Thread.currentThread().getId() + " end programm");
}
private static class TheThread extends Thread {
#Override
public void run() {
System.out.println(Thread.currentThread().getId() + " enter run");
while (!Temp.isVarSet()) {
System.out.println(Thread.currentThread().getId() + " running");
try {
Thread.sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
// ignore
}
}
System.out.println(Thread.currentThread().getId() + " exit run");
}
}
private static class Temp {
private volatile static boolean varSet = false;
public static void setVarSet() {
Temp.varSet = true;
}
public static boolean isVarSet() {
return Temp.varSet;
}
}
}
Can you please post a complete example?
Its working as expected without hanging the program.
private volatile static boolean varSet = false;
public synchronized static void setVarSet() {
varSet = true;
}
public synchronized static boolean isVarSet() {
return varSet;
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (!TestDemo.isVarSet()) {
// System.out.println("I am still here");
}
System.out.println("Variable set");
}
});
t1.start();
Thread.sleep(1000); // put delay to give the chance to execute above thread
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// Model model= new Model();
// View view = new View();
// Controller controller=new Controller(model, view);
setVarSet();
}
});
}
Consider the following code:
class Chicks {
synchronized void yack(long id) {
for(int x = 1; x < 3; x++) {
System.out.print(id + " ");
Thread.yield();
}
}
}
public class ChicksYack implements Runnable {
Chicks c; //.....(1)
public static void main(String[] args) {
new ChicksYack().go();
}
void go() {
c = new Chicks(); //........(2)
new Thread(new ChicksYack()).start();
new Thread(new ChicksYack()).start();
}
public void run() {
c.yack(Thread.currentThread().getId());
}
}
When i run this code, I am getting a Null Pointer Exception that I have not initialized variable c. But didn't i initialized it at line ....(2)? I am having trouble getting this concept. Does threading has a part to play in this exception?
Look at this line:
new Thread(new ChicksYack()).start();
^^^^^^^^^^^^^^^^
The attribute c of the newly created ChicksYack object is never initialized. In the go() method you only initialize c for the current (this) object.
That's why you get an NPE in the run() method. A good solution would be to initialize that variable in a default constructor for ChicksYack.
In the go() method, you're instantiating two new ChickYack objects, which have a null c. You should put the c = new Chicks() in your ChicksYack constructor.
Disclaimer: This code is copied from synchronized blocks for static and non-static methods
I made some modification to it. I want to know how to make threads call both synchronized static and non-static methods. I can make it work by wrapping the non-static method in a synchronized block. Is there any other way?
public class StaticNonStaticSynch
{
public static void main(String[] args)
{
final StaticNonStaticTest staticNonStaticTest = new StaticNonStaticTest();
Runnable runnable1 = new Runnable()
{
#Override
public void run()
{
staticNonStaticTest.nonStaticMethod();
}
};
Runnable runnable2 = new Runnable()
{
#Override
public void run()
{
StaticNonStaticTest.staticMethod();
}
};
Thread thread1 = new Thread(runnable1, "First Thread");
Thread thread2 = new Thread(runnable2, "Second Thread");
thread1.start();
thread2.start();
}
}
class StaticNonStaticTest
{
void nonStaticMethod()
{
//synchronized (StaticNonStaticTest.class){
for(int i=0;i<50;i++)
{
System.out.println("Non - Static method called by " + Thread.currentThread().getName() +" : = "+i);
}
// }
}
static synchronized void staticMethod()
{
for(int i=0;i<50;i++)
{
System.out.println("Static method called by " + Thread.currentThread().getName() +" : = "+i);
}
}
}
Remember that this:
public class MyClass {
public synchronized void doSomething() {
// Do something
}
public synchronized static void doSomethingStatic() {
// Do something static
}
}
Essentially compiles to this:
public class MyClass {
public void doSomething() {
synchronized(this) {
// Do something
}
}
public static void doSomethingStatic() {
synchronized(MyClass.class) {
// Do something static
}
}
}
Notice that they don't synchronize on the same thing. To fix this, create an object for both of them to lock on (known as a mutually exclusive object, or a "mutex"):
public class MyClass {
private static final Object MUTEX = new Object();
public void doSomething() {
synchronized(MUTEX) {
// Do something
}
}
public static void doSomethingStatic() {
synchronized(MUTEX) {
// Do something static
}
}
}
That should make it so that only one of these two methods are running at the same time across multiple threads.
A couple tips:
Always use synchronized(variable) on a variable that's final.
The MUTEX doesn't have to be strictly a mutex, it could be an actual object. See the example below.
Remember how the synchronized modifier on methods is effectively implemented. It's just like a synchronized block on this or MyClass.class.
Besides having an object that's strictly a mutex, you can use any field that's final. For example, to synchronize on a Map during iteration:
public class MyClass {
private static final Map<String, String> map = new HashMap<String, String>(); // Java 6
private static final Map<String, String> map = new HashMap<>(); // Java 7
public static void put(String k, String v) {
synchronized(map) {
map.put(k, v);
}
}
public static void printAll() {
synchronized(map) {
for (Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}
}
This code guarantees that you'll never get a ConcurrentModificationException
You can have both methods internally synchronize on a common lock object. Otherwise, the only way to have the instance method block while the static method executes is to synchronize on the class object (as you have in the commented lines).
Synchronized instance methods synchronize on the object instance; synchronized static methods synchronize on the class instance. Note that synchronized static methods might execute simultaneously if there are two instances of the class (say, from different class loaders). You usually would know if this is happening, because you have to do considerable work to make it happen.
Here's one way to synchronize both static and instance methods on a common lock object:
class StaticNonStaticTest {
private static final Object LOCK_OBJECT = new Object();
void nonStaticMethod() {
synchronized (LOCK_OBJECT) {
for (int i=0; i<50; i++) {
System.out.println("Non - Static method called by "
+ Thread.currentThread().getName() + " : = " + i);
}
}
}
static void staticMethod() {
synchronized (LOCK_OBJECT) {
for (int i=0; i<50; i++) {
System.out.println("Static method called by "
+ Thread.currentThread().getName() +" : = "+i);
}
}
}
}
I believe variables used in static main method should be also static as well.
The problem is that I cannot use this in this method at all. If I remember correctly, I have to initiate thread with commnad myThread = new ThreaD(this).
The below codes produces an error because I used this in thread initiation.
What have I done wrong here?
package app;
public class Server implements Runnable{
static Thread myThread;
public void run() {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
System.out.println("Good morning");
myThread = new Thread(this);
}
}
You can't use this because main is a static method, this refers to the current instance and there is none. You can create a Runnable object that you can pass into the thread:
myThread = new Thread(new Server());
myThread.start();
That will cause whatever you put in the Server class' run method to be executed by myThread.
There are two separate concepts here, the Thread and the Runnable. The Runnable specifies what work needs to be done, the Thread is the mechanism that executes the Runnable. Although Thread has a run method that you can extend, you can ignore that and use a separate Runnable.
Change new Thread(this) to new Thread(new Server()):
package app;
public class Server implements Runnable{
static Thread myThread;
public void run() {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
System.out.println("Good morning");
myThread = new Thread(new Server());
}
}
class SimpleThread extends Thread {
public SimpleThread(String name) {
super(name);
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " thread: " + getName());
try {
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {}
}
System.out.println("DONE! thread: " + getName());
}
}
class TwoThreadsTest {
public static void main (String[] args) {
new SimpleThread("test1").start();
new SimpleThread("test2").start();
}
}
public static void main(String args[]) throws Exception {
int maxScore = 0;
Thread student = new Thread(client,????);
student.start();
}
I want student thread to change value of maxScore, how do I do it in Java? (Like in C we can pass the address of maxScore)
You need a class object, if you want to modify value in separate thread. For example:
public class Main {
private static class Score {
public int maxScore;
}
public static void main(String args[]) throws Exception {
final Score score = new Score();
score.maxScore = 1;
System.out.println("Initial maxScore: " + score.maxScore);
Thread student = new Thread() {
#Override
public void run() {
score.maxScore++;
}
};
student.start();
student.join(); // waiting for thread to finish
System.out.println("Result maxScore: " + score.maxScore);
}
}
You can't. There is no way you can change the value of a local variable from another thread.
You can, however, use a mutable type that has an int field, and pass it to the new thread. For example:
public class MutableInt {
private int value;
public void setValue(..) {..}
public int getValue() {..};
}
(Apache commons-lang provide a MutableInt class which you can reuse)
Update: for a global variable you can simple use public static fields. Note that if you are willing not only to store some values in them, but also read them and do stuff depending on that, you would need to use synchronized blocks, or AtomicInteger, depending on the usages.
Also, you can use array (of one element):
public class Main {
public static void main(String args[]) throws Exception {
final int[] score = new int[1];
score[0] = 1;
System.out.println("Initial maxScore: " + score[0]);
Thread student = new Thread() {
#Override
public void run() {
score[0]++;
}
};
student.start();
student.join(); // waiting for thread to finish
System.out.println("Result maxScore: " + score[0]);
}
}
adding Synchronized to the methods was a solution for me, thanks