Calling a method of a class which extends Thread, from another class - java

I know this is a bit naive question but I want to understand the basic working principle behind multi-threading in java. Consider the following code and say A is executed in Main thread and it starts execution of another worker thread ,defined in class B. I want to know that can B.func1 called from A and run method of B, be executed in parallel or not?
public class A {
public static void main(String[] args) {
B obj = new B();
obj.start();
obj.func1();
}
}
public class B extends Thread {
public B() {
//constructor
}
public void run() {
while(true) {
//do somethings
}
}
public void func1() {
//do someotherthings
}
}

There is no magic behind a method call. If you call method from a thread, it is called in exactly the same thread. So since obj.func1() is called from main, it will be run in the main thread. It doesn't matter which class it belongs to or whether or not it extends Thread.
The new thread starts by executing run. Everything called from run and so on will be executed in parallel to main.

It's important to understand the difference between a thread and a Thread.
A thread is an independent execution of your code. Often when we talk about how some method or another works we say things like, "It tests the variable x, and if x is less than zero it calls the foobar method..."
Ok, but what is the "it" in that sentence? It is not the method. Methods don't do anything. A method is just a list of instructions, like the list of chores that somebody left for their housemate to perform. The list doesn't do the chores, it's the housemate that does the work (or so we might hope).
The "it" is a thread. Threads are entities in the operating system that execute methods (i.e., they do the chores).
A Thread, on the other hand, is a Java object that your program can use to create and manage new threads. Your program creates a new Thread object by doing:
thread t = new Thread(...);
[Oops! See what I just did? It's not your program, that does the work, it's your program's main thread, or maybe some other thread in your program. It's an easy thing to forget!]
Anyway, it subsequently creates the new thread by calling t.start();
Once you understand all that, then Sergey Tachenov's answer becomes obvious: Calling the methods of a Thread object really is no different from calling methods of any other kind of object.

There are multiple issues with your code. I have corrected them and added one more statement to print Thread Name in func1().
Working code:
public class A {
public static void main(String args[]){
B obj = new B();
obj.start();
obj.func1();
}
}
class B extends Thread{
public B (){
//constructor
}
public void run(){
while(true){
//do somethings
}
}
public void func1 (){
//do someotherthings
System.out.println("Thread name="+Thread.currentThread().getName());
}
}
output:
Thread name=main
Since you are directly calling func1() from main method (A.java) , you will get Thread name = main in output.
If you add same print statement run() method, you will get output as : Thread name=Thread-0

Related

Function as a function parameter in Java

I have a class, with Thread as superclass, I pass a function as a parameter and this class just execute that function. This class uses it to create threads, so I can execute any function in a thread without having to create a different class.
public class ThreadEjecucionLambda extends Thread {
Runnable funcion;
public ThreadEjecucionLambda(Runnable funcion)
{
this.funcion=funcion;
}
public void run()
{
funcion.run();
}
}
Now, to create several threads of a same method I use a 'for' block, for example:
for(Computer computer: Persistencia.getListComputers())
{
ThreadEjecucionLambda hilolambda=new ThreadEjecucionLambda(()->logica.EnciendeMonitor(computer.getNombrePC()));
hilolambda.run();
}
What I want to achieve is to generalice the previous 'for' so that I can execute a method,to which I will pass ,as parameters, (following the example) a list of 'Computers' and a function. This method will execute the 'for' block and will create a thread for each 'Computer, so I will pass as a parameter the previous function to the thread and that function will have, as a parameter, the 'Computer'.
What I want to get is something like this (WARNING: IT'S WRONG):
public void EjecutaHilosLambdaSegundo(ArrayList<Computer> listapcs,Runnable funcion)
{
for(Computer computer: listapcs)
{
ThreadEjecucionLambda hilolambda=new ThreadEjecucionLambda(funcion(computer));
hilolambda.run();
}
}
I hope I have explained myself well because it's a very confusing problem.
Thread already has a constructor taking a Runnable as argument, and executing it when you start it, so your subclass is useless and confusing. Not only that, but you never actually start any thread. So you could just run the Runnable directly, without creating any Thread or ThreadEjecucionLambda.
If I understand correctly, you want to execute the same function, taking a Computer as argument, on a list of Computers.
You don't need a Thread to do that. All you need is a Consumer<Computer>:
public consumeAllComputers(List<Computer> computers, Consumer<? super Computer> function) {
computers.forEach(function);
}
But, as you see, this method is useless, since you could just call forEach on the List directly.
So, suppose you want to print the name of each computer in a list, you would use
computers.forEach(computer -> System.out.println(computer.getName());
Don't reinvent the wheel!
For the synchronous solution, look at #JB Nizet answer.
Asynchronous solution
First, your ThreadEjecucionLambda class is not creating thread, because to start a new thread, you need to call the start() method of Thread.
public class ThreadEjecucionLambda extends Thread {
Runnable funcion;
public ThreadEjecucionLambda(Runnable funcion)
{
super(funcion);
this.funcion = funcion;
}
public void run()
{
super.start();
}
}
Second, this class is meaningless! Thread is already working that way.
Third, Runnable as is does not accept argument. What you actually need to do is create your own Runnable that takes a Computer as an argument.
public class MyRunnable implements Runnable {
Computer computer;
public MyRunnable(Computer computer)
{
this.computer = computer;
}
#Override
public void run()
{
// Do what you want cause a pirate is-
// Erm do what you want with your computer object
}
}
And then use it for your above method.
public void EjecutaHilosLambdaSegundo(ArrayList<Computer> listapcs, MyRunnable myRunnable)
{
for(Computer computer: listapcs)
{
Thread myThread = new Thread(myRunnable);
myThread.start();
}
}

How does multithreading method invocation work

I am using java.
I have an instance a of class A which has a public method foo() running and 2 other threads - threadB and threadC, all running at the same time.
here's class A
public class A {
int val = 0
public void foo(int incValue) {
a += incValue;
}
public static void main (String arg[]) {
MyThread a = new MyThread(this);
new Thread(a).start();
MyThread b = new MyThread(this);
new Thread(b).start();
}
}
here's the thread definition for threadB and threadC:
public class MyThread implements Runnable {
A main = null;
public MyThread(A main) {
this.main = main;
}
public callFoo(int incValue) {
main.foo(incValue);
}
#Override
public void run() {
//valToInc can be a value from a GUI form.
callFoo(valToInc);
}
}
If in threadB invokes callFoo(1) and threadC invokes callFoo(3) at the same time, then:
- Which thread will be able to call the method first?
- What is the result of the val in main class after both executions?
- Will the execution of the method for each thread happen concurrently or one after another?
There is absolutely no difference in how the JVM will invoke two methods "in parallel".
In other words: if you want to know what happens when a method is called, you can look here.
When a method is called "twice" in parallel, then that whole thing ... just happens twice!
Things become interesting when that method is making updates on that class, or in other objects! (like changing a field of your object, or appending a value to a list, ... )
You see, the real complexity of multi-threading is not about running some code in parallel. The real issue is what happens to "shared data".
If you find my answer to general; sorry - that is probably the best you can expect for such a generic question.
If [] threadB invokes callFoo(1) and threadC invokes callFoo(3) at the same time, then: - Which thread will be able to call the method first?
Threads run independently of each other. If there is no synchronization (there's none in your example), then any number of threads can be in calls to the same method at the same time.
Whenever a thread calls a method, it creates an activation record to hold all of the local variables and parameters of that method, and when several threads call the same method at the same time, each thread gets its own activation record. The threads can neither communicate with one another through the args and locals, nor can they interfere with one another's use of the args and locals.
They can, of course communicate and interfere with each other through any shared objects, including objects that may be referenced by the args or the locals.

How method preference work in java?

I just want to understand how below code snippet work ?
class AnnaThread extends Thread {
public static void main(String args[]){
Thread t = new AnnaThread();
t.start();
}
public void run(){
System.out.println("Anna is here");
}
public void start(){
System.out.println("Rocky is here");
}
}
Output - Rocky is here
There's not much to explain.
You override start() with code that prints Rocky is here
then you call start() which prints Rocky is here.
(the run method is never involved)
People often confuse the purpose of start and run. See for instance this question:
Why we call Thread.start() method which in turns calls run method?
The rules are simple:
Thread.run is an ordinary method (no magic)
Thread.start contains some magic because it spawns a separate thread (and lets that thread invoke run).
If you override Thread.start with your own method, then there's no magic left anywhere.
what you have here is a Java class which extends the Thread class (http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html)
class AnnaThread extends Thread {
then in your main method you create a new instance of the class which is a Thread (since the class extends the Thread)
public static void main(String args[]){
Thread t = new AnnaThread();
then you call the method start which follows bellow
t.start();
which prints
System.out.println("Rocky is here");
you could as well call the other method if you add the following line in your code
t.run();
in which case the method run would be executed which would print
System.out.println("Anna is here");

What the use of Thread constructor with string param?

Looking at the Thread constructors, I see there is one that takes single string parameter. I have the below code, which is kind of useless. I would like to know, how to make a fruitful use of this constructor and make something actually run
public class ThreadTest {
public static void main(String[] args) {
Thread t = new Thread("abc");
t.start();
System.out.println("Complete");
}
}
Or Is it not supposed to be used the way I demonstrated above?
I perfectly know how to write multiple threads and execute :), I am just trying to understand the correct use of this constructor? Should it only be used by calling super(name) by extending Thread and not by the way I am using it above.
The thread class in itself doesn't do all that much. You have to extend it or construct it around a runnable to make it perform a task when run. From the doc:
start(): "Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread."
run(): "If this thread was constructed using a separate Runnable run object, then that Runnable object's run method is called; otherwise, this method does nothing and returns."
Therefore constructing a new thread in your fashion and starting it does nothing. One use of the Thread(String) constructor is in subclasses:
public class Worker extends Thread{
public Worker(int numb){
super("worker-"+numb);
}
#Override
public void run(){
//Stuff this thread actually does when run
//....
for(int i = 0; i < 10; i++)
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
To answer your second question in the comments, this is how you would write code that's executed in parallel. Consider the above class plus this main method:
public static void main(String[] args){
Worker w1 = new Worker(1);
Worker w2 = new Worker(2);
w1.start();
w2.start();
}
The run methods of w1 and w2 will be executed in parallel. The order of the print statements will vary between executions of the main method.
This particular constructor is used to specify the 'name' of a thread, which can later be used to distinguish between instances of a specific thread type.
From the official Java API documentation;
Thread
public Thread(String name)
Allocates a new Thread object. This
constructor has the same effect as Thread (null, null, name).
Parameters: name - the name of the new thread
Once you have allocated a Thread a name, you can call the getName() method on the Thread instance to return the name it was given when it was created. This can be useful for debugging or for distinguishing between instances of of the same Thread subclass type.
Extra Reading:
Official Guide - Defining and Starting a Thread
If you simply call this constructor you get a Thread which does nothing. Why? Look at the source code of java.lang.Thread. It has a private Runnable target; class variable. When you call this constructor, the target variable remains set to null (because this constructor simply sets the Thread's name).
Also, the run() method of java.lang.Thread looks like this:
public void run() {
if (target != null) {
target.run();
}
}
So it means that this run() method will do nothing as target is null.
In order to create/start a Thread which really does something useful read here:
The Java tutorial - how to run a thread?

Calling functions from threads

I am beginner in java. I have been studying multithreading. I want to create two threads and these two threads must run separate methods concurrently. Here these threads should call sum and diff method and run simultaneously. But I am getting an error, that method should be of thread type. How to achieve it.
class Demo implements Runnable
{
void sum()
{
//Some lines of code
}
void diff()
{
//Some lines of code
}
public void run ()
{
System.out.println("Inside run");
}
}
class Test
{
public static void main (String []args){
Demo o = new Demo ();
Demo o1 = new Demo ();
Thread th = new Thread (o);
Thread th1= new Thread(o1);
th.start();
th1.start();
o.th.sum(); // getting error here
o1.th1.diff(); // getting error here
}
}
First of all you have a compilation error because you're trying to reference the variable th as a field on an object of type Demo. th is not a field, but rather a local variable and can be referenced directly (i.e. without the o. prefix). Second, sum() and diff() cannot be called against an instance of Thread as those methods are not defined by thread, but rather by your own Demo class.
All that being said, these compilation problems aren't even the root issue for this code. Based on your code it seems you have some fundamental misunderstandings about the syntax and structure of Java programs so it might benefit you to go through some entry-level tutorials before trying to tackle concurrent programming. But, for the sake of completeness here is a brief explanation of what you need to do in order to make your program work.
When you call Thread.start() it's going to fork a thread and call the run() method of the Runnable you passed into that thread object's constructor.
In order to call the two different methods you need to create two different classes that implement runnable and put the two method implementations in each of their run methods.
Example:
public class Sum implements Runnable {
public void run() {
//Add up your numbers
}
}
public class Diff implements Runnable {
public void run() {
//Subtract numbers
}
}
public class Test {
public static void main(String[] args) {
Thread sumThread = new Thread(new Sum());
Thread diffThread = new Thread(new Diff());
sumThread.start();
diffThread.start();
}
}
Assuming that you are getting a compilation error, the statement o.th.sum() is incorrect.
The statement o.th will cause the compiler to look for a public static class level field in the Demo class with the name th. Since there is no such field in Demo class, you get an error.
You are getting this error because you are trying to access the Thread's local variable using the object of the Demo class and you can't call the method directly if you want's it to run it in a separate thread. A new thread will spawn only when you call start() method on thread class and then it will execute the code in run() method.
As per your requirement to create two threads and these two threads must run separate methods concurrently, following code should work.
class Demo implements Runnable
{
public void run ()
{
//sum() method code
}
}
class Demo1 implements Runnable
{
public void run ()
{
//diff() method code
}
}
class Test
{
public static void main (String []args){
Demo o = new Demo ();
Demo1 o1 = new Demo1 ();
Thread th = new Thread (o);
Thread th1= new Thread(o1);
th.start();
th1.start();
}
}

Categories