Sharing the same data area in JAVA multithreading? - java

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.

Related

If a class has an inner class and the inner class runs a thread, do the inner class threads share the same fields of the outer class with one another?

Basically, if I have the code:
public class Outer {
public int counter = 0;
public void makeNewThread() {
Thread t1 = new Thread(new Inner());
t1.start();
}
private class Inner implements Runnable {
public void run() { //do stuff involving counter... }
}
}
Everytime makeNewThread() is called, will each thread have their own version of counter, or will they all share the same version of counter? I would assume they would all share the same version since it's an inner class, but each thread has their own stack so I'm not sure.
They will share the same counter.
If you have only a single instance of Outer, you will have only a single instance of counter. All the threads will share it.
Important! Validate concurrency and visibility issues accessing the counter from different threads. Most probably you need to use AtomicInteger instead of "int" or wrap all the access code (for both write and read operations) into a synchronize block.

Java Multithreading : how does thread creation with Runnable interface work?

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

How to ensure a method is using a single instance at a time

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.

Are these classes thread-safe?

First class:
class Main1 {
private ExecutorService service = Executors.newFixedThreadPool(4);
public static void main(String[] args) {
Main1 m = new Main1();
m.start();
}
public void start() {
final MyObject obj = new MyObject();
obj.doSomeCalculation();// after this point not to modify obj in main thread
service.submit(new Runnable(){
public void run() {
obj.doSomething(); // is it threadsafe doing this?
}
});
}
}
Second class:
class Main2 {
private ExecutorService service = Executors.newFixedThreadPool(4);
public static void main(String[] args) {
Main2 m = new Main2();
m.start();
}
public void start() {
class Job implements Runnable {
public MyObject obj;
public void run() {
obj.doSomething(); // is it threadsafe doing this?
}
}
Job job = new Job();
job.obj.doSomeCalculation(); // after this point not to modify obj in main thread
service.submit(job);
}
}
Are Main1 and Main2 threadsafe? Does Main1 and Main2 make different sense to thread-safety?
update:
neither doSomeCalulation() nor doSomething() don't have any lock or synchronized block. I want to known whether doSomething() could always read the correct states that doSomeCalculation() change to obj
Are Main1, Main2 threadsafe?
In the Main1 case, the thread-safety of the application depends on whether MyObject is thread-safe and whether any other threads doing things with it. However, the obj.doSomething(); statement is thread-safe assuming nothing else is changing the object
In fact, the obj.doSomething(); statement doesn't use the variable in the enclosing class. Instead, the value of that variable is passed to the inner class in a hidden constructor argument. The other thing that makes this thread-safe is that there is an implicit synchronization between the parent and child threads when a new thread is created. (Reference - JLS 17.4.4 Synchronization Order) These two facts combined mean that the Runnable.run() method will get the correct reference, and that the child thread will see the state of the object at the synchronization point (or later).
In the Main2 case, the same applies. In this case you are merely doing explicitly (more or less) what is happening implicitly in the Main1 case.
UPDATE - the above reasoning applies even if you mutate the object in the parent thread (as per your updated question) before passing it to the child thread ... because of the implicit synchronization that I mentioned. (However, if the parent thread were to change MyObject after the submit() call, you'd run into thread-safety problems.)
Does Main1 and Main2 make different sense?
I don't know what you are asking. If you are asking if there is any benefit in using an inner class rather than an anonymous inner class ... in this case the answer is no. They behave the same with respect to thread-safety.
Actually, the Main1 version is better because its is simpler, more readable (to an experienced Java developer), and more robust. The Main2 class exposes the obj field for other code to potentially access or even update. That's bad style. You could fix that, but only by adding more code ... which brings us back to simplicity / readability.
The way your code is structured, you submit your job (in both cases) only after you have already performed the calculation above. So there is no chance of those two actions happening in parallel and so there are no data races.
However, if you were to perform your calculations after submitting the job/Runnable to the executor service, then those two calculations could happen in parallel and there could be a data race.
Job job = new Job();
service.submit(job);
// Now there is a data race!!!
job.obj = ...// do some calculation, and after this point not to modify obj in main thread

accessing shared variable from inside a Runnable class

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

Categories