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()
}
}
Related
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.
This is a pseudocode version of my current working code:
public class DataTransformer {
private final boolean async = true;
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
public void modifyAsync(Data data) {
if (async) {
executorService.submit(new Runnable() {
#Override
public void run() {
modify(data);
}
});
} else {
modify(data);
}
}
// This should actually be a variable inside modify(byte[] data)
// But I reuse it to avoid reallocation
// This is no problem in this case
// Because whether or not async is true, only one thread is used
private final byte[] temp = new byte[1024];
private void modify(Data data) {
// Do work using temp
data.setReady(true); // Sets a volatile flag
}
}
Please read the comments. But now I want to use Executors.newFixedThreadPool(10) instead of Executors.newSingleThreadExecutor(). This is easily possible in my case by moving the field temp inside modify(Data data), such that each execution has it's own temp array. But that's not what I want to do because i want to reuse the array if possible. Instead I want for each of the 10 threads a temp array. What's the best way to achieve this?
As static variable is shared between all Threads, so you could declare as static. But if you want to use different values then either use Threadlocal or use different object.
With ThreadLocal you could do :
ThreadLocal<byte[]> value = ThreadLocal.withInitial(() -> new byte[1024]);
You could also use object like this:
public class Test {
public static void main(String[] args) {
try {
Test test = new Test();
test.test();
} catch (Exception e) {
e.printStackTrace();
}
}
class Control {
public volatile byte[] temp = "Hello World".getBytes();
}
final Control control = new Control();
class T1 implements Runnable {
#Override
public void run() {
String a = Arrays.toString(control.temp);
System.out.println(a);
}
}
class T2 implements Runnable {
#Override
public void run() {
String a = Arrays.toString(control.temp);
System.out.println(a);
}
}
private void test() {
T1 t1 = new T1();
T2 t2 = new T2();
new Thread(t1).start();
new Thread(t2).start();
}
}
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));
I'm trying to figure out how synchronized methods work. From my understanding I created two threads T1 and T2 that will call the same method addNew, since the method is synchronized shouldn't it execute all the iterations of the for loop for one thread and then the other? The output keeps varying, sometimes it prints it right, other times it prints values from T1 mixed with T2 values. The code is very simple, can someone point out what am I doing wrong? Thank you.
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new A());
Thread t2 = new Thread(new A());
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
public class B {
public synchronized void addNew(int i){
Thread t = Thread.currentThread();
for (int j = 0; j < 5; j++) {
System.out.println(t.getName() +"-"+(j+i));
}
}
}
public class A extends Thread {
private B b1 = new B();
#Override
public void run() {
b1.addNew(100);
}
}
Each A instance has its own B instance. The method addNew is an instance method of B. Therefore, the lock acquired implicitly during calls to addNew is the lock on the receiver B instance. Each thread is calling addNew on a different B, and therefore locking on different locks.
If you want all B instances to use a common lock, create a single shared lock, and acquire it in the body of addNew.
Both A objects have their own B object. You need them to share a B so the synchronization can have an effect.
try this :
public class Main {
public static void main(String[] args) {
A a = new A();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
class B {
public synchronized void addNew(int i){
Thread t = Thread.currentThread();
for (int j = 0; j < 5; j++) {
System.out.println(t.getName() +"-"+(j+i));
}
}
}
class A extends Thread {
private B b1 = new B();
#Override
public void run() {
b1.addNew(100);
}
}
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();
}
}