java: Passing a class reference to another thread - java

I'm trying to learn how to use multithreading in Java. I have a main and two classes which extend Thread, A and B. I want the main to start A, which makes multiple calls to B. Once A is finished, I want B to send something to main.
The main creates two threads, one A and one B, and then starts both threads. A does something, which will then pass on a result to B. The main then collects an answer from B and does something else. I don't know how to get the total from B back to the main.
I'm also not sure how to instantiate the two classes (threads) but then give A a reference of B since Java uses pass-by-value. Can someone give me some pointers.
public static void main(String[] args)
{
B b = new B();
A a = new A(100, b);
B.start();
A.start();
A.join(); // Waiting for A to die
// Here I want to get a total from B, but I'm not sure how to go about doing that
}
public class A extends Thread
{
private int start;
// Some reference to B
B b;
public A (int n, B b) {
int start = n;
this.b = b;
}
public void run() {
for (int i = 0; i < n; i++) {
b.add(i);
}
}
}
public class B extends Thread
{
private int total;
public B () {
total = 0;
}
public void add(int i) {
total += i;
}
}

I changed your example code into what I consider to be a more meaningful example.
Communication between threads is usually handled through shared data (or channels like pipes, sockets - but I wont go there...). And while it is perfectly alright to have this shared data contained within the thread classes I have seperated the shared data from the data/methods used to administer the threads.
I hope this helps you to understand the relationship between threads and data objects.
public class TestThreads {
public static void main(String[] args)
{
DataShare ds = new DataShare();
B b = new B(ds);
A a = new A(100, ds);
b.start();
a.start();
try {
a.join(); // Waiting for A to die
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println ("Accumulated total from B = " + b.getTotal());
b.endThread();
}
}
public class DataShare {
private int value;
public DataShare () {
value = -1;
}
public synchronized boolean setValue(int val) {
boolean valueSet = false;
if (value == -1) {
value = val;
valueSet = true;
}
return valueSet;
}
public synchronized int getValue() {
int val = value;
value = -1;
return val;
}
}
public class A extends Thread {
private int max;
private DataShare dataShare;
public A (int n, DataShare ds) {
max = n;
dataShare = ds;
}
public void run() {
int i = 0;
while (i < max) {
if (dataShare.setValue(i)) {
i++;
}
}
}
}
public class B extends Thread {
private int total;
private DataShare dataShare;
private boolean running = false;
public B (DataShare ds) {
dataShare = ds;
total = 0;
}
public void run() {
running = true;
while (running) {
int nextValue = dataShare.getValue();
if (nextValue != -1) {
total += nextValue;
}
}
}
public int getTotal() {
return total;
}
public synchronized void endThread() {
running = false;
}
}
I am aware that this naive example is far from optimal since both threads are wasting precious cycles while waiting for the value to be set/read. I just wanted to keep the example as simple as possible while still addressing the point I'm trying to make.

A decent way to do it. You just pass an instance of class A:
public class Foo {
public void doFoo() {..} // that's the method you want to use
}
public class Bar {
private Foo foo;
public Bar(Foo foo) {
this.foo = foo;
}
public void doSomething() {
foo.doFoo(); // here you are using it.
}
}
And then you can have:
Foo foo = new Foo();
Bar bar = new Bar(foo);
bar.doSomething();

First of all, B should not be a thread. If all it does is respond to messages from A, then it can just be an object like any other.
Second, while everyone says java uses pass by value, the confusing part is that object references are passed by value, so objects are effectively passed by reference. Thus, you can pass B to A, and get the total from your copy of B.

If we look at your code:
B b = new B();
A a = new A(100, b);
B.start();
A.start();
A.join(); // Waiting for A to die
// Here I want to get a total from B, but I'm not sure how to go about doing that
You are passing a pointer of b to A. That means that if class A only accesses class B directly (it does not replace it with a new instance of B) that the object should contain anything that class A did to it. In other words, both your main code and class A work on the same object of B. So you should be able to get the total of b simply by asking the object you have instantiated in main.
So if you call
b.total();
at the end of main, it should return your value (of course you must ensure that thread A will not make changes to it after retrieving the value).

I assume that you are trying to achieve communication between the two threads you create in the main method. This is, however, not happening. I made a few changes to your code and included it below to show what I think you wanted to do.
First, a few corrections of your examples:
You cannot use class names (A and B) when referencing thread objects as you do in the main method. Use the object names instead (a and b).
In class A constructor you are creating a new local variable start instead of referencing the member variable. Hence: int start = n should be start = n
I'm guessing you want to loop the number of times set in constructor. Hence for (int i = 0; i < n; i++) { should be for (int i = 0; i < start; i++) {
Pass by reference/value is not really relevant here. Object references are passed by value as anything else is. It is, however, the contents of the reference variable (the object address) which is interesting and that will not change. In other words, when passing an object reference to a method, the method WILL address that specific object, and any change made to the contents of the objects will be visible outside the method as well.
Here are your examples with a few corrections as I think you intended them.
public class TestThreads {
public static void main(String[] args)
{
B b = new B();
A a = new A(100, b);
b.start();
a.start();
try {
a.join(); // Waiting for A to die
} catch (InterruptedException e) {
e.printStackTrace();
}
// Getting a total from b is simple, if you provide the method for it
System.out.println ("Accumulated total from B = " + b.getTotal());
}
}
public class A extends Thread {
private int start;
// Some reference to B
B b;
public A (int n, B b) {
start = n;
this.b = b;
}
public void run() {
for (int i = 0; i < start; i++) {
b.add(i);
}
}
}
public class B extends Thread {
private int total;
public B () {
total = 0;
}
public void add(int i) {
total += i;
}
public int getTotal() {
return total;
}
}
Now, here is the problem with these examples:
An object is not a thread and vice versa. In the main thread (lets call that thread tM) You are creating an object of class B and forking a new thread (thread tB) starting in its run() method. However, since you did not override the run method, the threat ends immediately after creation.
Then you create an object of class A. Gives it the reference to object b (which has nothing to do with thread tB) and fork a new thread (thread tA). Here you did implement a run() method. The result is the following:
Thread tM did the initial work and is now waiting for thread tA to finish.
Thread tB was started and died immediately afterwards
Thread tA is doing all the work of incrementing the counter of object a, and making object b add the counter to its sum.
When tA finished after 100 increments tM wakes up and acquires the sum from object b (which again has nothing to do with thread tB).

Related

Synchronized method does not work but synchronized block does, why?

public class driver{
public static void main(String[] args) {
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
PrintNum secondObjectForThread = new PrintNum(0);
secondObjectForThread.startNewThread();
}
This is the class that the driver calls:
public class ClassName implements Runnable{
int variableForUpdate;
private Thread t;
private static ArrayList<Integer> intArray;
public ClassName(int variableForUpdate) {
super();
this.intArray = new ArrayList<Integer>();
this.variableForUpdate = variableForUpdate;
for (int i = 0; i < 30 ; i++) {
this.intArray.add(i);
}
}
#Override
public void run() {
runThisWhenThreadStarts();
}
private synchronized void runThisWhenThreadStarts() {
System.out.println("Started");
for (int i = 0; i < 30; i++) {
System.out.println(intArray.get(i));
}
}
public void startNewThread() {
t = new Thread(this);
t.start();
}
}
If I use block synchronization the following, the output is synchronized:
private void runThisWhenThreadStarts() {
synchronized (ClassName.class) {
System.out.println("Started");
for (int i = 0; i < 30; i++) {
System.out.println(intArray.get(i));
}
}
}
I have been troubleshooting this for many hours and cannot figure out... Can anyone shed some light please?
I also notice if I use the same object to call startNewThread(), the synchronization will work. But I don't understand why.
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
firstObjectForThread.startNewThread();
I want to use two different object from the same class instead of one object calling the method twice (the workaround above).
I am able to use the synchronized methods in another program, with 2 different instances (get and put) :
public class Hello extends Thread {
int x;
Coffee x1;
int threadno;
Hello(int x, Coffee x1) {
this.x = x;
threadno = x;
this.x1 = x1;
}
public void run() {
switch (x) {
case 0:
System.out.println("Start thread " + threadno + " Get");
break;
case 1:
System.out.println("Start thread " + threadno + " Put");
break;
}
ops();
System.out.println("Stopping thread " + threadno);
}
public void ops() {
x1.get();
}
public static void main(String[] args) {
Coffee c1 = new Coffee();
Hello get = new Hello(0, c1);
Hello put = new Hello(0, c1);
get.start();
put.start();
}
}
Hello class will call coffee class:
class Coffee {
boolean available = false; // indicating there nothing to get.
// waiting on each other.
int contents = 55;
public synchronized int get() {
System.out.println("Entering Get method " + contents);
for (int i = 0; i < 30; i++) {
System.out.println(i);
}
return contents;
}
}
In the first example, the method acquires the lock on the object instance that the method is called on. The block doesnt do that, instead it acquires the lock on the class.
Taking the lock on the instance has no effect on the other thread, it is a different object. Both threads are acquiring their own lock, which is useless. Neither thread is prevented from doing anything.
Taking the lock on the class means both threads are trying to acquire the same lock. For locking to work the same lock has to be used by both threads.
In the second example the Coffee object is shared by both threads, and both threads are trying to acquire the same lock on the Coffee object. That means the second thread to get to the lock has to block until the lock is released by the first thread, locking successfully keeps the thread out until the first thread is done.
To understand synchronized, keep track of what locks are being acquired.

Unable to understand sync

Hey I am trying to make 10 threads in a synchronized manner and I came up with the code below however I am not able to understand a part of it as mentioned below. I am still really new to java, I tried looking up synchronized threading from
Here but still I am clueless.
class question3 {
public static void main(String arg[]) throws Exception {
for (int i = 0; i < 11; i++) {
data di = new data();
System.out.println(di.count);
}
}
}
class item {
static int count = 0;
}
class data extends item implements Runnable {
item d = this;
Thread t;
data() {
t = new Thread(this);
t.start();
}
public void run() {
d = syn.increment(d);
}
}
class syn {
synchronized static item increment(item i) {
i.count++;
return (i);
}
}
I am not sure what this part of code does?
public void run() {
d = syn.increment(d);
}
}
class syn {
synchronized static item increment(item i) {
i.count++;
return (i);
}
}
the run function is used when starting the thread, this is a must function you need to override when implement Runnable. When calling Thread.start(), the run function will be called.
The class syn contains a synchronized method, it is simply mean that only one thread can access it each time, thus make the incerment function thread safe.
object d has a static variable count meaning all instances of item class (and data ) share the same count, so all threads increment the same variable
the line d = syn.increment(d); is basically count++ but in a thread safe way

Using volatile variable from properly object reference

I want to make an object in a new thread, that will create another thread. In that last created threads I need a reference for variable from exact object that created this thread. So far I have this code:
Main
public static void main(String[] args) {
for(int i = 0; i < 2; i++){
ClassThread ct = new ClassThread();
Thread t = new Thread(ct);
t.start();
}
}
ClassThread
public static volatile int liczba = 1;
private static int id = 0;
#Override
public void run() {
for(int i = 0; i < 2; i++){
Class1 cla = new Class1(liczba, id);
Thread t = new Thread(cla);
t.start();
id++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Class1
private volatile int var;
private int id;
public Class1(int _var, int _id) {
var = _var;
id = _id;
}
#Override
public void run() {
while(true){
System.out.println("Thread: " + id + " : " + var);
var++;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
If you need to get an int reference from one thread to another, you either have to specify your own MutableInteger class, or use AtomicInteger. The atomic integer has the positive side-effects in that operations can be made atomic. For a more exhaustive answer, see This answer.
If the question is regarding non-primitive types, you can simply pass the needed reference to the constructor as you are already attempting to do. Any changes to the internal state of that object will be reflected to all holders of a reference. Some objects are immutable (String being the perhaps most well-known, but be aware that Integer, Long, etc. works the same way.), and can therefore not be used in this way.
Do note that if you pass a reference, any assignments done to your internal reference var = "hello"; will not affect anything outside your class. You will simply exchange your private reference for another one, leaving all other references to the old object as they are. This has to do with the fact that Java is always pass-by-value.

Ensuring all waiting threads complete

I'm building a system where the progress of calling threads is dependent on the state of two variables. One variable is updated sporadically by an external source (separate from the client threads) and multiple client threads block on a condition of both variables. The system is something like this
TypeB waitForB() { // Can be called by many threads.
synchronized (B) {
while (A <= B) { B.wait(); }
A = B;
return B;
{
}
void updateB(TypeB newB) { // Called by one thread.
synchronized (B) {
B.update(newB);
B.notifyAll(); // All blocked threads must receive new B.
}
}
I need all the blocked threads to receive the new value of B once it has been updated. But the problem is once a single thread finishes and updates A, the waiting condition becomes true again so some of the other threads become blocked and don't receive the new value of B. Is there a way of ensuring that only the last thread that was blocked on B updates A, or another way of getting this behaviour?
I've got following idea: to keep counter of threads waiting for "good" value of B, first of them woken up will cache that good value and let other readers up to that moment read it. We keep new readers out of waiting loop till all previous round threads are done.
Here's outline of code:
final AtomicInteger A = new AtomicInteger(-1), B = new AtomicInteger(-1);
int cachedB = -1;
int readersCount;
int waitForB() throws InterruptedException { // Can be called by many threads.
synchronized (B) {
while (cachedB != -1) B.wait();
readersCount ++;
while (A.get() <= B.get()) { B.wait(); }
if (cachedB == -1) {
cachedB = B.get();
A.set(B.get());
readersCount--;
if (readersCount == 0) { cachedB = -1; B.notifyAll(); }
return B.get();
} else {
int ret = cachedB;
readersCount--;
if (readersCount == 0) { cachedB = -1; B.notifyAll(); }
return ret;
}
}
}
void updateB(int newB) { // Called by one thread.
synchronized (B) {
B.set(newB);
B.notifyAll(); // All blocked threads must receive new B.
}
}
My suggestion is about to use an event based approach, where the threads want to know about the new B value just register about the changes! and the single thread just call(trigger) them out.
something like this.
first declare the event sign.
interface EventListener{
void onUpdate(TypeB oldOne,TypeB newOne);
}
then have an implementation as listener.
class ManyThread implements EventListener,Runnable{
...
private TypeA a;
synchronized void onUpdate(TypeB oldOne,TypeB newOne){
if(!oldOne.equals(newOne)){a=newOne;this.notify();}
}
public ManyThread(){SingleThread.registerListener(this);}
public synchronized void run(){
this.wait();//waiting for an event!
//some business
}
...
}
then provide the event publisher.
final class EventMgr{//would be as a singleton guy too
private EventMgr(){}
static private java.util.List<EventListener> li=new java.util.ArrayList<EventListener>();
static synchronized public void registerListener(EventListener e){li.add(e);}
static synchronized void triggerListeners(TypeB oldOne,TypeB newOne){
for(EventListener e:li){e.onUpdate(oldOne,newOne)}
}
}
and simple trigger listeners by the EventMgr guy
class SingleThread{
TypeB oldOne,B;
void updateB(TypeB newB) { // Called by one thread.
synchronized (B) {
oldOne=B.clone();
B.update(newB);
//B.notifyAll();
EventMgr.triggerListeners(oldOne,B);
}
}
}
I'm not sure if this is 100% thread safe but I haven't found any issues yet. The idea is something like this:
CyclicBarrier barrier;
AtomicInteger count = 0;
TypeB waitForB() { // Can be called by many threads.
synchronized (B) {
count++;
while (A <= B) { B.wait(); }
count--;
{
if (barrier != null) { barrier.await(); }
return B;
}
class UpdateA implements Runnable {
void run() {
A = B;
}
}
void updateB(TypeB newB) { // Called by one thread.
synchronized (B) {
B.update(newB);
barrier = new CyclicBarrier(count, new UpdateA);
B.notifyAll(); // All blocked threads must receive new B.
}
}

Java guarantees initialization safety for immutable objects?

To prove initialization safety for immutable objects, I wrote a small program. Even though fields were final, second thread was able to view the half-constructed object being created by the first thread. Have I got the concept wrong or "object escaping" can cause it? Second thread first printed "10 null" and then after half of the iterations it started printing "10 apple".
package test;
import java.util.ArrayList;
import java.util.List;
public final class ObjectEscape implements Runnable {
private final int a;
private final String b;
//this list is defined somewhere else
public static volatile List<ObjectEscape> globalList = new ArrayList<ObjectEscape>();
public ObjectEscape () throws InterruptedException {
a = 10;
globalList.add(this);
Thread.sleep(10);
b = "apple";
System.out.println("done");
}
public ObjectEscape(int a) {
this.a = 1;
b = "";
}
public static void main(String are[]) throws InterruptedException{
Thread t = new Thread(new ObjectEscape(1));
t.start();
ObjectEscape oe1 = new ObjectEscape();
}
#Override
public void run() {
int i=0;
while(i<10) {
if(globalList.get(0) != null)
System.out.println(globalList.get(0).a+" "+globalList.get(0).b);
i++;
}
}
}
final fields are guaranteed to have been initialized when the contructor call finishes. Naturally, a "leaking this" will subvert the value of this guarantee:
globalList.add(this); // ObjectEscape.<init> has not finished yet
See also: Java leaking this in constructor

Categories