Suppose I have the following thread:
public class MyThread {
public void run() {
while (true) {
// do something forever
}
}
}
Then I instantiate the thread as follows:
MyThread thread = new MyThread();
What happens if I now call
thread.performSomeFunction()
Specifically, how does performSomeFunction interact with the infinite loop above? Does it have to wait for the loop to sleep? Or can they both run "concurrently"?
If your thread.performSomeFunction() is called from another thread, it does not have to contend with the infinite loop that is being run in the run() method. In this case, your MyThread instance is treated like another object that can have methods called on it.
Note that your infinite loop will not start until you start your thread instance.
You can test this out by putting the following line in both the run() method and your perfomrSomeFunction() method:
System.out.println("in [METHOD NAME]: " + Thread.currentThread().getName());
and replace the [METHOD NAME] with the actual method name.
Related
Ok, guys so my teacher uses this code to start a thread if a thread is not already active. But i have been taught that to run threads no matter if its runnable or extending thread, you start it by the start method and not run. But in this case he starts it with run, why is that?
public void start2(Runnable r) {
if (thread == null) {
thread = new Thread(new Runnable() {
public void run() {
r.run();
thread = null;
}
});
thread.start();
}
}
Your teacher starts thread with thread.start() . He just implemented the runnable interface inside the Thread object initialization which is the absolutely correct approach.
A more modern approach would be to use an Executor to run the thread:
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
String threadName = Thread.currentThread().getName();
System.out.println("Hello " + threadName);
});
You have a better control of the thread:
Can retrieve some result (with futures)
Know if your thread is over (executor.isTerminated())
Request/force a shutdown (executor.awaitTermination()/executor.shutdownNow()).
These functionalities are not natively supported by the thread.start() that your teacher shows you (which is, by the way, a good way to launch a thread).
For more about Executors, I advice this excellent tutorial.
The r.run(); part in your code is just a method call to your Runnable r input parameter, which will be an implementation of the Runnable interface.
This does not start a thread
It's just a method call that is executes the input's implementation of Run method.
It will execute just like any other method.
Then, the actual thread will start at thread.start();
Long answer:
What is happening here is, first checking the thread variable.
If its null then initialize a new Thread with an anonymus class thread = new Thread(/*here --> */new Runnable() {.... and implementing the run() method.
Inside the run() there is a call, made to the outer method's input param, called Runnable r with r.run(); then set the thread variable to null.
Just outside of the if statement, the teacher starts the thread with thread.start();.
Code:
public class ThreadTest {
public static void main(String[] args) {
MyImlementThread mit = new MyImlementThread();
Thread t = new Thread(mit);
t.start();
t = new Thread(mit);
t.start();
}
}
// MyImlementThread
class MyImlementThread implements Runnable {
public void run() {
System.out.println("This is implemented run() method");
}
}
/*
Output
This is implemented run() method
This is implemented run() method
*/
What happens here is the main thread starts two threads and exits. Each of the new threads writes a message to stdout, then ends. At that point since all the non-daemon threads have finished the JVM exits.
The posted code is confusing on account of it defining a Runnable but giving it a name ending in Thread.
A Thread object relates to an os-level thread, calling start on a Thread makes the code in the run method of the passed-in Runnable execute run on a separate thread from the one that called start.
The Runnable defines a task but doesn't specify how it runs. It could be passed into a specific Thread's constructor or submitted to an Executor or run by the current thread.
In this case the Runnable declared has no state, no instance variables are declared. Here two threads can execute the same Runnable without a conflict because there is no shared state. The printstream that writes to the console is synchronized, so the lines written by the threads each get written one at a time and don't get jumbled together.
Can anyone explain to me why the first thread doesn't work and the second works perfectly:
public class Test {
public static void main(String args[]) throws InterruptedException {
TestThread1 t1 = new TestThread1();
TestThread2 t2 = new TestThread2();
t1.startThread();
t2.start();
Thread.sleep(4000);
t1.stopThread();
t2.stopThread();
}
}
class TestThread1 extends Thread {
private volatile TestThread1 thread;
public void startThread() {
thread = new TestThread1();
thread.start();
}
public void run() {
while (thread != null) {
System.out.println("RUNNING 1 ...");
}
}
public void stopThread() {
thread = null;
}
}
class TestThread2 extends Thread {
private volatile boolean finished = false;
public void run() {
while (!finished) {
System.out.println("RUNNING 2 ...");
}
}
public void stopThread() {
finished = true;
}
}
When I debug inside TestThread1 class: Inside startThread, the thread member is filled (so it is not null), inside run, thread member is null!!! And finally, inside stopThread, the thread member is not null!!!
Can anyone explain to me what is happening here?
Here, you have two instances of TestThread1 t1:
One is stored into your t1 local variable (in your main method).
One is stored into your thread instance variable (of t1).
t1 is never started, t1.thread is.
t1.stopThread() sets t1.thread to null, but it doesn't affect t1.thread.thread.
Since you're starting t1.thread, its run method is using t1.thread.thread:
This is never set to anything (so it's using null).
Calling t1.stopThread() like you do would only set t1.thread to null, which wouldn't affect t1.thread.thread.
More generally, you can't just "kill" a thread as such, but you can implement tests within the method to tell it to return under certain circumstances. What you've done with your second test is closer to this (using while (!finished) { ... } with a volatile variable).
I wouldn't limit the test to finished. It's also useful to test whether the thread was interrupted, in particular because if you run your runnables within an ExecutorService shutdownNow() will try to interrupt them (see this question).
I'd use while (!finished && !Thread.currentThread().isInterrupted()) { ... }.
(Note the difference between Thread.currentThread().isInterrupted() and Thread.interrupted(): they may seem similar, but the latter will also reset the status, which you might not want.)
Depending on what's within your loop (or whether there is a loop at all), you may want to use something like if (finished || Thread.currentThread().isInterrupted()) { return; } at various strategic points, where it makes sense.
There is two TestThread1 object being created, one is started and the other is stopped.
I suggest not extending Thread and instead wrapping your Runnable once.
TestThread1 t1 = new TestThread1();
t1.startThread();
This will simply call method startThread() on object t1. Inside this method you are creating a new Thread.
thread = new TestThread1();
thread.start();
But for this Thread thread instance variable is null(It is not null for t1).
So in both cases thread variable should be null.
Because in your main method you create a Thread1 Object. You then run startThread which creates a different Thread1 object inside the first one and sets it to the field thread. You then start the second object which didn't have its own thread field initialized. When run method is run on the second object the condition is false and the while loop doesn't start.
Your object hierarchy looks something like this
t1 (Thread1) {
thread(Thread1): {
thread: null;
run() {
while (thread != null) {...} // this is the method that is run - thread is null here since you never initialized it
}
};
startThread() {} // calls the run method on the nested thread object above
run() {
while (thread != null) {...} // this method is not run since t1.start() is never called in main()
}
}
in your case,
t2.start();
is calling run method directly, it is not creating thread inside startThread method.
so t1.stopThread() makes the volatile thread inside Thread1 class null. so you are getting like that.
solution
use
t1.startThread();
t2.startThread();
instead of
t1.startThread();
t2.start();
which makes 2 threads to create separate threads inside that method.
if you want a single thread of Thread1 then use runnable interface and create 2 threads and call startThread respectively rather than creating extra threads inside main.
I have a class "TestRunnable" which overrides run method by implementing Runnable.
Running overridden run method, as follow :
TestRunnable nr = new TestRunnable();
Thread t = new Thread(nr);
t.setName("Fred");
t.start();
What if i directly call t.run();
What happen if we don't call t.start(); ?
The run method is just another method. If you call it directly, then it will execute not in another thread, but in the current thread.
Here's my test TestRunnable:
class TestRunnable implements Runnable
{
public void run()
{
System.out.println("TestRunnable in " + Thread.currentThread().getName());
}
}
Output if only start is called:
TestRunnable in Fred
Output if only run is called:
TestRunnable in main
If start isn't called, then the Thread created will never run. The main thread will finish and the Thread will be garbage collected.
Output if neither is called: (nothing)
If you call start method then a separate thread will be allocated to execute the run method, means you achieve multi threading . But when you call run method directly then it becomes a normal method and main method itself will execute the run method , means no multi threading.
If run() method is called directly instead of start() method in Java code, run() method will be treated as a normal overridden method of the thread class (or runnable interface). This run method will be executed within the context of the current thread, not in a new thread.
Example
Let’s create a class and spawn two threads and cause some delay in the execution if they are real threads then there will be context switching – while one thread is not executing another thread will execute. When the start method is not called no new threads are created thus there won’t be any context switching and the execution will be sequential.
public class MyThreadClass extends Thread{
#Override
public void run(){
System.out.println("In run method " + Thread.currentThread().getName());
for(int i = 0; i < 5 ; i++){
System.out.println("i - " + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyThreadClass mc1 = new MyThreadClass(“MyThread1”);
MyThreadClass mc2 = new MyThreadClass();
mc1.run();
mc2.run();
}
}
Alright, I'm new to threading, so my question might be pretty dumb. But what I want to ask is, I have this class, let's say its name is MyClass.java. And then inside one of its methods is callThread(), which I want to print something out, sleep, and return control to MyClass.java's method. How do I do that?
Currently, my code goes something like this:
class MyClass {
void method()
{
MyThread thread = new MyThread();
thread.run();
// do some other stuff here...
}
}
And then, this will be the MyThread:
class MyThread implements Runnable {
public void run()
{
while (true)
{
System.out.println("hi");
this.sleep(1000);
}
}
}
I was hoping that MyThread would print "hi", pass back control to MyClass, and then print "hi" again one second later. Instead, MyThread freezes up my entire program so having it in there doesn't work at all...
Is there any way around this?
You should be callig thread.start()
More on that in the manual: Defining and Starting a Thread
You must have to call start() method of Thread class.
MyThread thread = new MyThread();
Thread th=new Thread(thread);
th.start();
sleep() is an instance method of Thread class and MyThread class is not a thread (It's a runnable) so you need to use Thread.currentThread().sleep() method.
while (true)
{
System.out.println("hi");
try{
Thread.currentThread().sleep(1000);
}catch(Exception ex){ }
}
Read this tutorial for more info on thread.