How do i reference a method from a different threads java - java

I'm trying to reference thread a from thread b, I essentially want to use the getN() method in B class/thread, any help is appreciated
//// class help {
///// main {
Thread a = new Thread(new A());
Thread b = new Thread(new B(a));
}
}
class A implements Runnable {
private static int tally;
public void run() {
}
public int getN() {
tally = 6;
return tally;
}
}
class B implements Runnable {
private A aref;
public B(A ref){
aref=ref;
}
public void run() {
aref.getN();
}
}
//////////////////////////////////////////////////////////////////
/////////////////////////

In order to construct an object of class B you need a reference to object of class A, not to the object of class Thread. So this should work:
A objA = new A();
Thread a = new Thread(objA);
Thread b = new Thread(new B(objA));

Related

Java Runnable without static reference

I am trying to learn multi-threading using the runnable interface but I am having some trouble figuring out how to pass information. Basically, in the example below, I want to remove the static reference from the Hashmap but if I do that, the program breaks. How do I pass the hashmap to the runnable interface class without using the static keyword?
public class ThreadDemo {
static HashMap <String, Integer>map = new HashMap<>();
public String Hi() {
return "hi";
}
public String Hello() {
return "Hello";
}
public void addToMap(String item) {
if (map.containsKey(item)) {
map.put(item, map.get(item) + 1);
} else {
map.put(item, 1);
}
}
public static void main(String[] args) throws InterruptedException {
ArrayList<Thread> all = new ArrayList<>();
for (int i = 0; i < 50; ++i) {
threader threader = new threader();
all.add(new Thread(threader));
}
for (Thread thread : all) {
thread.start();
}
for (Thread thread : all) {
thread.join();
}
ThreadDemo td = new ThreadDemo();
System.out.println(td.map);
}
}
And a class that implements Runnable
public class threader implements Runnable {
ThreadDemo td = new ThreadDemo();
#Override
public void run() {
synchronized(td.map) {
td.addToMap(td.Hi());
td.addToMap(td.Hello());
}
}
}
A class instance is all about information.
public class threader implements Runnable {
final private ThreadDemo td;
public threader(ThreadDemo td) {
this.td = td;
}
#Override
public void run() {
..
}
}
then to use (details omitted, just the idea):
ThreadDemo theTd = new ThreadDemo();
for (...) {
threader threader = new threader(theTd);
all.add(new Thread(threader));
}
....
Of course, all threads are using the same ThreadDemo, with the same map, so you'll need to ensure access is interlocked in some way, e.g., by using synchronized. The ThreadDemo.addToMap method should be synchronized in this example, rather than the caller of addToMap. This puts the responsibility for the "care of the map" into the place that actually owns the map, and is consequently a better design.
I chose to share the ThreadDemo rather than just the map inside the ThreadDemo, since it looks to me that the intent of ThreadDemo is just to be a wrapper around the map.

Passing command-line arguments to mutliple java threads

I'm trying to create multiple threads in a java program and have them perform arithmetic operations on integers passed as command-line arguments. Obviously neither of the thread classes I'm trying to pass to are in the main method so how can I still access a variable like args[0] from these classes?
public class Mythread {
public static void main(String[] args) {
Runnable r = new multiplication();
Thread t = new Thread(r);
Runnable r2 = new summation();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}
class summation implements Runnable{
public void run(){
System.out.print(args[0]);
}
}
class multiplication implements Runnable{
public void run(){
System.out.print(args[1]);
}
}
You should pass in the necessary information in the constructor
class Summation implements Runnable {
private final String info;
public Summation(String info) {
this.info = info;
}
#Override
public void run(){
System.out.print(info);
}
}
Then you can pass in the args values to your threads in main so that you have them in your runnables / threads
public class Mythread {
public static void main(String[] args) {
Runnable r = new multiplication(args[1]);
Thread t = new Thread(r);
Runnable r2 = new summation(args[0]);
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}

Passing a Runnable object to a class extending Thread class and then starting it prints unexpected result

I heard about an interview question from one of my friend.
What happens when we pass a Runnable object to an object of a class extending Thread class and start the class.
public class A extends Thread {
Runnable obj;
public A(Runnable obj) {
this.obj=obj;
}
public void run() {
System.out.println("Printing A")
}
}
public class B implements Runnable {
public void run() {
System.out.println("Printing B");
}
}
public class MainApp {
public static void main() {
B b = new B();
A a = new A(b);
a.start();
}
}
Now it outputs Printing A
I was expecting Printing B as it is a perfect analogy to
Thread obj = new Thread(Runnable runnableObj)
Can someone please explain me this weird output??
Thread has a run method which essentially calls runnable.run(). Except that in your class A you have overriden that method to do something else.
So runnable.run() is not called any longer...
You are creating an instance of class A (Now it is a Thread).
Then you are calling start() of that Thread using instance a.
You are just passing a Runnable object as a normal instance variable to class A.
There is nothing complicated in that.
The result is normal.
With a tiny adjustment your code runs as expected.
public class A extends Thread {
Runnable obj;
public A(Runnable obj) {
this.obj = obj;
}
public void run() {
System.out.println("Printing A");
obj.run();// <---- I added this.
}
}
public class B implements Runnable {
public void run() {
System.out.println("Printing B");
}
}
public void test() {
B b = new B();
A a = new A(b);
a.start();
}
The problem is that you are overriding the run() method on Thread and never pass the Runnable obj to super(). Try this:
public class A extends Thread {
public A(Runnable obj) {
super(obj);
}
public class B implements Runnable {
public void run() {
System.out.println("Printing B");
}
}
public void test() {
B b = new B();
A a = new A(b);
a.start();
}
}

How to switch between two thread back and forth

I have two methods in two different classes, like this
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
System.out.println("This is A and B ");
}
}
#Override
public void run() {
methodAandB();
}
}
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
System.out.println("This is A or B");
}
}
#Override
public void run() {
methodAorB(a);
}
}
Thread t1 is calling methodAandB().
Thread t2 is calling methodAorB().
Can I switch between these two threads after each iteration of loop in methods?
I want to get output like this:
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
Best example of flip-flop between threads:
Given two int array (even and odd), 2 threads printing their numbers in natural order.
package com.rough;
public class ThreadsBehaviour {
static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
int a[] = {1,3,5,7,9};
int b[] = {2,4,6,8,10};
Thread odd = new Thread(new Looper(a, lock));
Thread even = new Thread(new Looper(b, lock));
odd.start();
even.start();
}
}
class Looper implements Runnable
{
int a[];
Object lock;
public Looper(int a[], Object lock)
{
this.a = a;
this.lock = lock;
}
#Override
public void run() {
for(int i = 0; i < a.length; i++)
{
synchronized(lock)
{
System.out.print(a[i]);
try
{
lock.notify();
if(i == (a.length - 1))
{
break;
}
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
You can achieve this simply by using the shared variables. I have implemented and verified the problem. code is below
class X
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassXdone)
{}
System.out.println("This is A and B ");
GlobalClass.isClassXdone = true;
GlobalClass.isClassYdone = false;
}}
#Override
public void run() {
methodAandB(); } }
ClassY
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassYdone)
{}
System.out.println("This is A or B ");
GlobalClass.isClassYdone = true;
GlobalClass.isClassXdone = false;}}
#Override
public void run() {
methodAorB();}}
Definition of the shared variable
public class GlobalClass {
public static boolean isClassXdone = false ;
public static boolean isClassYdone = false ;
}
You can just start your thread using t1.start and t2.start to get the desired output
Thread t1 = new Thread(new ClassX());
Thread t2 = new Thread(new ClassY());
t1.start();
t2.start();
This is probably more than needed to solve the problem, but, as it seems to be an introduction to concurrent programming exercise, it should be along the lines of what you'll encounter.
You should probably have a shared object that both your threads know, so that they may synchronize through it. Like so:
public class MyMutex {
private int whoGoes;
private int howMany;
public MyMutex(int first, int max) {
whoGoes = first;
howMany = max;
}
public synchronized int getWhoGoes() { return whoGoes; }
public synchronized void switchTurns() {
whoGoes = (whoGoes + 1) % howMany;
notifyAll();
}
public synchronized void waitForMyTurn(int id) throws
InterruptedException {
while (whoGoes != id) { wait(); }
}
}
Now, your classes should receive their respective identifier, and this shared object.
public class ClassX implements Runnable {
private final int MY_ID;
private final MyMutex MUTEX;
public ClassX(int id, MyMutex mutex) {
MY_ID = id;
MUTEX = mutex;
}
public void methodAandB() {
for(int i = 0; i < 10; i++) {
try {
MUTEX.waitForMyTurn(MY_ID);
System.out.println("This is A and B ");
MUTEX.switchTurns();
} catch (InterruptedException ex) {
// Handle it...
}
}
}
#Override
public void run() { methodAandB(); }
}
ClassY should do the same. Wait for its turn, do its action, and then yield the turn to the other.
I know it's a little late to answer this. But it's yesterday only I have come across this question. So I guess it's never too late.. ;)
Solution, as #afsantos mentioned is having a shared object between the two threads and implementing mutual exclusion on the shared object. The shared object could be alternatively locked by the two threads. Two possible implementations are as follows. This is actually more like an extension of #afsantos solution. His work is hereby acknowledged.
Solution 1:
Blueprint of the object that will be shared is as follows.
public class MutEx {
public int whoGoes, howMany;
public MutEx(int whoGoes, int howMany) {
this.whoGoes = whoGoes;
this.howMany = howMany;
}
public synchronized void switchTurns(){
this.whoGoes = (this.whoGoes + 1) % 2;
notifyAll();
}
public synchronized void waitForTurn(int id) throws InterruptedException{
while(this.whoGoes != id)
wait();
}
}
Then, you could implement the ClassX as follows.
public class ClassX implements Runnable {
private final int MY_ID;
private final MutEx MUT_EX;
public ThreadOne(int MY_ID, MutEx MUT_EX) {
this.MY_ID = MY_ID;
this.MUT_EX = MUT_EX;
}
#Override
public void run(){
this.doTheWork();
}
public void doTheWork(){
for(int i = 0; i < 10; i++){
try {
MUT_EX.waitForMyTurn(MY_ID);
System.out.println("This is A and B");
MUT_EX.switchTurns();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ClassY also will be the same, with whatever the differences you need to be there. Then, in the invocation (i.e. in the main method),
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
Thread t1 = new Thread(new ClassX(0, mutEx);
Thread t2 = new Thread(new ClassY(1, mutEx));
t1.start();
t2.start();
}
Voila! You have two threads, alternating between each as you need.
Solution 2: Alternatively, you could implement the ClassX & ClassY as follows.
public class ClassX extends Thread{
Here, you are subclassing the java.lang.Thread to implement your requirement. For this to be invoked, change the main method as follows.
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
ClassX t1 = new ClassX(0, mutEx);
ClassY t2 = new ClassY(1, mutEx);
t1.start();
t2.start();
}
Run this, and you have the same result.
If you don't need to use Thread try this code:
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
methodAandB();
} else {
methodAorB();
}
}

Locking on static object

There are multiple instance of Class A that runs at a time.
Class A calls multiple instances of Class B in its run.
public Class Main {
public static void main(String args[] ) {
A a1 = new A();
Thread t1 = new Thread(a1);
t1.start();
A a2 = new A();
Thread t2 = new Thread(a2);
t2.start();
}
}
Class A implements Runnable {
public void run() {
B b1 = new B();
Thread t11 = new Thread(b1);
t11.start();
B b2 = new B();
Thread t21 = new Thread(b2);
t21.start();
}
}
There is method named "method" in class B where a Set Collection is edited. That edit is done based on static lock in Class B.
EDIT-
Class B implements Runnable {
private final static Object LOCK = new Object();
private final static Set<T> busyRecords = new HashSet<T>();
public void waitToWorkOn(final T obj) {
synchronized(LOCK) {
while (busyRecords.contains(obj)) {
LOCK.wait(); //go to sleep
}
busyRecords.add(obj);
}
}
public void doneWith(final T obj) {
synchronized(LOCK) {
busyRecords.remove(obj);
LOCK.notifyAll();
}
}
public void mathod(obj) {
try{
waitToWorkOn(obj);
.. do some work with obj
}
finally {
doneWith(obj);
}
}
public void run() {
method(getObj())
}
}
But that Set does not need concurrency control when it is accessed from different "A" instances. Only within an A instance, it needs to be locked for all B instances.
By this I mean, that when 2 instances of A are running, they should not be made to wait. But within an A instance if 2 B objects pick same obj, they have to wait inside LOCK.wait.
I don't think that LOCK can be made non-static as A calls multiple instances of B.Can we tune LOCK object here for better concurrency across A objects.
You can create a thread-safe instance of the shared collection and pass it to all the Bs for a given A.
Class A implements Runnable {
public void run() {
// create shared set instance scoped to A, and make it thread-safe
Set col = Collections.synchronizedSet(new HashSet());
B b1 = new B(col);
Thread t11 = new Thread(b1);
t11.start();
B b2 = new B(col);
Thread t21 = new Thread(b2);
t21.start();
}
}
Class B implements Runnable {
private final Set<T> someSet;
private B(Set<T> someSet) {
this.someSet = someSet;
}
public void method(final T obj) {
someSet.add(obj);
}
public void run() {
method()
}
}

Categories

Resources