I need to define a shared variable in my Main class's main() method. I need two threads to be able to access that shared variable. Im creating the threads by implementing the Runnable interface and implementing the abstract run() method of the interface. How do i refer to the shared variable defined in the Main class's main() method from within the run() method defined in my class that implements the Runnable interface? Obviously just calling them by name is not working - as they appear out of my Runnable class's scope.
EDIT - apologies, here is a simple example
public Class DoThread implements Runnable {
public void run(){
sharedVar += 1
}
}
and in a separate .class file:
public Class Main {
public static void main(String[] args) {
int sharedVar = 0;
Thread t1 = new Thread(new DoThread());
Thread t2 = new Thread(new DoThread());
t1.start();
t2.start();
t1.join();
t2.join();
}
}
so should i be creating an object to store the shared var in and then passing that object to both the DoThread() constructors when creating the threads? I get confused sometimes between when java passes by ref or passes by var, so if i do it this way, will changes to the shared var by t1 be seen by t2?
Well, if you declare a local variable you won't be able to refer to that anywhere other than in classes created within that method.
Where are you implementing Runnable? If it's in the same class, then you could either make it an instance variable and make main set the variable on the same instance that you're creating the thread from, or make it a static variable. If Runnable is implemented in a different class, then when you construct an instance of that class you could give it the data it needs - it's not clear exactly what that means at this point... As others have said, code would be useful. (For example, do the threads need to be able to see changes in the original data?)
As an aside, threading is relatively advanced, whereas propagating data between classes is relatively basic. If you're new to Java, I'd recommend getting started on easier things than threading.
EDIT: For your example, you should use an AtomicInteger, like this:
import java.util.concurrent.atomic.AtomicInteger;
class DoThread implements Runnable {
private final AtomicInteger counter;
DoThread(AtomicInteger counter) {
this.counter = counter;
}
public void run() {
counter.incrementAndGet();
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
AtomicInteger shared = new AtomicInteger(0);
Thread t1 = new Thread(new DoThread(shared));
Thread t2 = new Thread(new DoThread(shared));
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(shared.get()); // Prints 2
}
}
Code would be useful.
If you are using an anonymous class, then you can declare the variables as final and they will be accessible in the anonymous class.
public void main(String[] args) {
final int myvar = 0;
new Thread(new Runnable() {
public void run() {
System.out.println("myvar: "+myvar);
}
}).start();
}
You need to pass a reference to the shared value. If its isn't a reference already you need to change it to an AtomicReference, AtomicInt etc or an array of the value you want to share.
This is the place where PassByRef is more effective. Pass your variable reference to both of runnable instances. Thats all... from then it can be referenced inside your run method.
Ex:
Thread th1 = new Thread (Myrunnable(varRef)). Similarly for other thread
Related
It is said that, if a class is implemented Runnabe interface, it can be turned into a thread, whose instances can share the same data area in the class. However, there is only run() method in Runnable interface, so how is this realized?
#La Kate, the sharing happens in a concrete class that implements Runnable. Such a class will have state, that is, fields that hold information about the Runnable instance. These fields are shared between every thread that uses the exact same Runnable instance. This is unlike the mistaken extends Thread idiom, where each thread has its own separate state.
So for example:
final Runnable runnable = new Runnable() {
final Object lock = new Object();
final ImportantInfo info = new ImportantInfo();
#Override
public void run() {
while (true) {
doABunchOfStuff();
synchronized (lock) {
info.load();
}
doABunchOfOtherStuff();
}
}
};
This Runnable instance can be sent to more than one Thread:
Thread footh = new Thread(runnable);
Thread barth = new Thread(runnable);
footh.start();
barth.start();
The two threads use the exact same Runnable, so that means each thread now shares state via the immutable lock object and the mutable info object. The former can synchronize access, and the latter can pass changes between threads.
However, there is only run() method in Runnable interface, so how is
this realized?
This is realized by introducing state in your runnables and then passing on same instances for those state objects. A runnable with no state doesn't share data.
Below is not a running or compiling code but just to give you a rough idea - there are two threads sharing a Student object. private Student student; introduces state to your runnable.
public class ExampleRunnable implements Runnable {
private Student student;
public void ExampleRunnable(Student student){
this.student=student;
}
#Override
public void run(){
.....do something with student here in synchronized way....
.....
}
and below is class where you create threads ,
public class MainClass {
public static void main(String[] args){
Student student = new Student();
Thread thread1 = new Thread(new ExampleRunnable(student));
Thread thread2 = new Thread(new ExampleRunnable(student));
/* So in above code, there are two different runnables and two different threads but both are using same Student object . This way you can share data among various runnables / threads. */
}
}
}
In fact the Runnable interface provides only a method to turn an object into a thread (it is an interface) it's not a structure to share variables, these objects can share variables using the "synchronized" modifier or other thread safe structures (you can find it in the oracle guide), but this is up to you.
Could someone explain what does this code does? new Thread(new X()).start();
Rest of the code:
class X implements Runnable {
X() {}
}
public static void main(String[] arg) {
new Thread(new X()).start();
}
}
This is a very simple example, which shows how to create a new thread and run it. When you create new threads in Java, you give them something to do - a "Runnable".
class X implements Runnable
This interface has only one method - run(). So you create a new thread, with a runnable in its' constructor.
new Thread(new X())
Once you have created a new thread, you have to start it with the start() method. This is when it calls the runnable's run() method. In your example, this has just been chained on after the construction of the thread:
new Thread(new X()).start();
Now, this example is unusual in that class X doesn't actually implement the run method. But normally, there's that extra bit, so your example would look like this:
class X implements Runnable {
public void run() {
System.out.println("This is running on a different thread!");
}
public static void main(String[] arg) {
new Thread(new X()).start();
}
}
You don't need to define a constructor if it's blank, first of all. It'll automatically be blank if you don't define one. Second of all, you can simply do an anonymous class definition, which I'll explain in a second. The method isn't main in this case, it's run. You can define a thread object using the anonymous class definition, too.
new Thread() {
#Override
public void run() {
//Code here
}
}.start();
The anonymous class definition allows you to define and instantiate a class which extends/implements another class both at the same time without actually creating the class. Also, note that X.main() is static, meaning that any instance of X will not have that method. You want to override run and call start. Start is just a method which calls run in a different thread. Note that you can't start a thread twice.
Every thread object has a method run(). if you call the start() method of thread object, then it will execute run().
The only difference is it will be executed separately/parallely and won't be in the existing sequence of operation.
You can create thread in two ways : one by extending Thread and other by implementing Runnable interface.
If you are not extending the Thread class,your class object would not be treated as a thread object. So you have to explicitly create Thread class object.
Thread class will take Runnable class as parameter in constructor.
You are passing the object of your class X that implements Runnable to Thread constructor so that your class run() method will be executed from start() method of Thread.
You can create threads in two different ways. Have a look at oracle documentation about thread creation
An application that creates an instance of Thread must provide the code that will run in that thread. There are two ways to do this:
Provide a Runnable object. The Runnable interface defines a single method, run, meant to contain the code executed in the thread. The Runnable object is passed to the Thread constructor
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Subclass Thread. The Thread class itself implements Runnable, though its run method does nothing. An application can subclass Thread, providing its own implementation of run
public class HelloThread extends Thread {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new HelloThread()).start();
}
}
Am new to multi threading programming, when I declare the run() method as static its giving the compiler error as
"This static method cannot hide the instance method from Thread".
I didn't understand what that means, so please help me.
public class hello extends Thread {
public static synchronized void run() {
for(int i=0;i<1000;i++)
System.out.println(i);
}
public static void main(String[] args) {
hello t1 = new hello();
hello t2 = new hello();
t1.start();
t2.start();
}
}
It is not necessarily relevent to multi-threaded programming, it is true of Java in general. If you have a class:
public class MySuperclass {
public void myMethod() {
//do stuff
}
}
You cannot then over-ride it to make it static:
public class MySubclass extends MySuperclass {
public static void myMethod() {
//do other stuff
}
}
This is not allowed.
That's what the error message means.
public void run();
is a Method declared in class Thread. As it's not static in Thread you cannot "change" it into a static method in your subclass. And given your example, you don't even need to do that.
If you need to have the code executed inside the Thread public and static and synchronized, I'd advise to refactor that part out:
#Override
public void run() {
staticRun();
}
public static synchronized void staticRun() {
for(int i=0;i<1000;i++)
System.out.println(i);
}
In the main() method you create two instances of Thread - t1 and t2 and then you call start() on them and that is correct you cannot run/start the class but an instance. That is why run() method is not supposed to be static. It needs an object (a Thread object) to be executed. Just remove static from your declaration and it shall be almost fine. Other thing is that you dont need to make your run method synchronized (it is counter productive - you use thread to execute in paralel and ynchronize only on specific parts never whole run method).
The instance method run() is already available in hello class due to inheritance. You are trying to create another method (static) with same name which is run().
If the method is not static, it will automatically override the implementation and hide the method instance of parent class..
So, is the Error.. Simple!
Because java is Object Oriented language and anything is java is object.
And task which you are trying to perform in multiple threads is object too and you should create this object. When object is created you should call start() method which is defined on Thread class. So to implement your own logic, you should override this behavior by implementing run() method in Hello subclass.
Run method defines logic which should be performed in other thread (note, that run method doesn't create new thread)
Start method tells java to create new native thread and perform your run method in this new thread
Try:
public class Hello extends Thread{
public void run()
{
for(int i=0;i<1000;i++)
System.out.println(i);
}
}
public class Main
{
public static void main(String[] args)
{
Hello hello t1 = new hello();
Hello hello t2 = new hello();
t1.start();
t2.start();
}
}
The thread Class has a run method, therefore if you define it again in the hello class then you are overriding it, (direct inheritance since Hello extends Thread) now, it makes no sense to turn a Object method into a Class method, (run method belongs to an object and not to the class) that is the reason why your compiler is complaining with the message:
"...you can not This static method cannot hide the instance method
from Thread".
in other words, you are violating inheritance rules with it.
This may be a simple question,but still it is a problem for me.I am having a class that have method called task and i want to ensure only one instance of this class can run this method at a time.I have implemented it like this and am i doing it correct way?
class A{
public void task(){
synchronized(A.this){
//method stuff
}
}
}
class B{
public static void main(String a[]){
new A().task();
}
}
class C{
public static void main(String a[]){
new A().task();
}
}
If B started the task and before it completes C also came to task i want to C to wait until B completes.
so far it seems works.But i want to know is this the correct way,
thank you.
Not quite. As you have it, you guarantee that only one thread will execute task() on a given instance at a time -- but separate instances can still run task() at the same time. That is, if you did this (in pseudo-code):
Thread t1 = new A().task();
Thread t2 = new A().task();
t1.start();
t2.start();
Then since each thread creates a separate instance of A, they'll each be able to run task() at the same time.
You need to synchronize on a static field (or A.class), or make task() a static, synchronized method (in which case synchronized locks based off of the Class object).
synchronized(A.this) will rely on your instance of A.
In your case, that instance could be different i.e a thread running B.main() and another thread running C.main() will both create a different instance of A. Therefore one of them will be able to access public void task() even though it's already being accessed by the other one.
If you only want to make sure that one thread at a time can access that task method, you can do it this way:
class A{
private static final Object myLock = new Object ();
public void task() {
synchronized(myLock) {
//method stuff
}
}
}
You could also have a look at the Locks.
I have the following setup in Java,
public class Main {
// starts sub class
SubClass sub = new SubClass();
sub.start();
// sub will keep running and call method alert() on a specif change
// method alert is void but updates a public variable named status on sub
while(1==1) {
// I should ideally be able to catch/read sub status result here
// how can I do it?
}
}
I'm new to Java so this may not be valid and my approach may be wrong. That being the case please point me in the right direction.
Thank you.
I presume SubClass.start() starts a new thread so the parent runs in parallel with the child. Then the main class can do a Object.wait() on the sub object, and the SubClass thread can do a Object.notify() on the sub object.
you should start by putting your code into a main method :)
If your SubClass is not already a Runnable,
public class Main
{
public static void main(String args[])
{
Thread myThread = new Thread(new Runnable()
{
public void run()
{
//Instantiate your SubClass here and do stuff. You can pass yourself as a parameter if you plan to do callbacks.
}
});
myThread.setDaemon(true);
myThread.start();
}
}
Alternatively if you've implemented the Runnable interface on SubClass then just use the thread mechanics (wait(), notify(), etc etc).