public class LambdaFunctionHandler implements RequestHandler<Object, String> {
#Override
public String handleRequest(Object input, Context context) {
Runnable runnable = new Runnable() {
#Override
public void run() {
System.out.println("Hello");
}
}
Thread thread1 = new Thread(runnable);
thread1.start();
Thread thread2 = new Thread(runnable);
thread2.start();
Thread thread3 = new Thread(runnable);
thread3.start();
Thread thread4 = new Thread(runnable);
thread4.start();
}}
I've tried normally and it works fine. but on the lambda function it will not work properly.
Thread is dying before the complete excution of threads. when return statement called it is automatically stopping threads.
Expected result
Hello
Hello
Hello
Hello
Actual Result
Hello
As people said in the comments, the problem is that you are not waiting for the threads to complete. You return from handleRequest() as soon as you're done starting threads. This tells Lambda that your execution is done, so it suspends your container before those threads have a chance to execute.
"Suspends your container" is the difference between running on Lambda and running locally. When you run locally the JVM actually exits, and it won't do so until all non-daemon threads have finished.
To ensure that all threads run, you need to call explicitly join them before returning from your handler function.
To help you understand how this works, you should also add some more debugging information (use System.err because it's unbuffered):
#Override
public String handleRequest(Object input, Context context) {
Runnable runnable = new Runnable() {
#Override
public void run() {
System.err.println("Hello from " + Thread.currentThread().getName());
}
};
Thread thread1 = new Thread(runnable);
thread1.start();
Thread thread2 = new Thread(runnable);
thread2.start();
Thread thread3 = new Thread(runnable);
thread3.start();
Thread thread4 = new Thread(runnable);
thread4.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
System.err.println("handler function exiting");
}}
Related
In python I can set a thread to be a daemon, meaning if parent dies, the child thread automatically dies along with it.
Is there an equivalent in Java?
Currently I am starting a thread like this in Java, but the underlying child thread does not die and hang even if main thread exits
executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
while (true) {
//Stopwatch stopwatch = Stopwatch.createStarted();
String threadName = Thread.currentThread().getName();
System.out.println("Hello " + threadName);
try {
Thread.sleep(1*1000);
} catch (InterruptedException e) {
break;
}
}
});
When you're interacting with bare Thread you can use:
Thread thread = new Thread(new MyJob());
thread.setDaemon(true);
thread.start();
In your example, there's ExecutorService that needs to be provided with ThreadFactory which should do the similar job - like this:
Executors.newSingleThreadExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
});
I would also recommend using Guavas ThreadFactoryBuilder:
Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder()
.setDaemon(true)
.build()
);
It eases setting the most common thread properties and allows for chaining multiple thread factories
update
As Slaw and Boris the Spider rightfully noticed - you have mentioned the behavior that would cause killing child-thread when parent-thread dies. There's nothing like that either in Python or Java. Daemon threads will be killed when all other non-daemon threads exited.
I am starting to learn threads. I have tried different types of thread creation. From the below code you can see the thread t4, target is new instance of Mythread1 & thread name is "Thread4".
But when I see the output I am not able to find the Thread name "Thread 4" instead I get the name "Thread-4". But this is a naming convention for a default thread name.
I am not able to understand what's wrong. I am sure its very basic mistake. Kindly correct me.
class MyThread1 extends Thread {
MyThread1() {
}
public MyThread1(String nameIn) {
super(nameIn);
}
public void run() {
System.out.println(this.getName());
}
}
class MyThread2 implements Runnable {
Thread ownThread;
public MyThread2() {
}
public MyThread2(String nameIn) {
ownThread = new Thread(this, nameIn);
}
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class ThreadCreation {
public static void main(String[] args) {
//Execution type1, as direct thread object
MyThread1 t1 = new MyThread1();
Thread t2 = new MyThread1();
Thread t3 = new Thread(new MyThread1());
Thread t4 = new Thread(new MyThread1(), "Thread4");
Thread t5 = new MyThread1("Thread5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
//Execution type2, pass the runnable object to thread constructor
Thread t11 = new Thread(new MyThread2());
Thread t22 = new Thread(new MyThread2(), "Thread22");
MyThread2 t33 = new MyThread2("Thread33");
t11.start();
t22.start();
t33.ownThread.start();
}
}
Output:
Thread-0
Thread-2
Thread-1
Thread-4
Thread5
Thread22
Thread-5
Thread33
But when I see the output I am not able to find the Thread name "Thread 4" instead I get the name "Thread-4". But this is a naming convention for a default thread name.
Your problem is in code like this:
Thread t4 = new Thread(new MyThread1(), "Thread4");
This code is using MyThread1 as a Runnable and not as a thread. So when the run() method is called you are then calling getName() on the MyThread1 instance and not on the thread that is actually running and calling your run() method and whose name is "Thread4". That is why the MyThread2 class works because it is using Thread.currentThread() to display the true running thread's name.
When you create a thread, either you need to extend Thread and start it as new MyThread1("Thread4") or implement Runnable and do new Thread(new MyRunnable1(), "Thread4");. Implementing of Runnable is the recommended pattern since it allows you to extend other classes.
You never want to do something like new Thread(new ClassThatExtendsThread(), "name"). That creates a fake Java Thread instance that is going to just confuse you.
In your MyThread1 you print the name of the thread object the method is in. Since you don't specify another name when creating the object, a sequential name "Thread-4" is generated for you.
You should either print the name of the executing thread, like in MyThread2, or create the MyThread1 object with a name:
Thread t4 = new Thread(new MyThread1("Thread4"));
I tried to create a five threads, accordingly if one thread invokes the synchronized method on one object(objsyn in this case) then all other threads should wait till the thread finishes with the object. So the output should come from thread 1 to thread 5 in order. But the output is coming out of order.
class synctest extends Thread
{
public synchronized void display()
{
try{Thread.sleep(5000*((long)(Math.random())));}
catch(Exception e){}
System.out.println("From synchornized thread "+ Thread.currentThread().getName());
}
public synchronized void run()
{
synctest objsyn = new synctest();
objsyn.display();
}
public static void main(String args[])
{
synctest objsy = new synctest();
Thread t1 = new Thread(objsy,"Thread 1");
Thread t2 = new Thread(objsy,"Thread 2");
Thread t3 = new Thread(objsy,"Thread 3");
Thread t4 = new Thread(objsy,"Thread 4");
Thread t5 = new Thread(objsy,"Thread 5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
Thread execution order is not guaranteed. Synchronization make sure only one thread executing that block of code at a point of time, it doesn't care whether it is first thread (or) second thread.
If you want really execute a particular logic in order, then you don't really need threading. Remember that when you start a thread, it will be separate thread from main thread. May be answers for this question help you.
I have an example that seems strange to me.
public class Join {
public static void main(String[] args) {
Thread t1 = new Thread(
new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
);
Thread t2 = new Thread(t1);
t1.setName("t1");
t2.setName("t2");
t1.start();
try {t1.join();} catch (InterruptedException ie) {}
t2.start();
}
}
We'll see printed only t1.
If we'll comment "t1.join", we'll se the expected output (t1 t2).
Why ?
The second thread is created incorrectly:
Thread t2 = new Thread(t1);
I can't support it by documentation, but in the source code of Thread.run() I see:
if (target != null) {
target.run();
}
Where target is Runnable instance. When the Thread is done, it clears the target variable:
private void exit() {
//...
target = null;
This means that when the first thread is done (join() method) it clears the target and the second thread does nothing. When join() is removed, both access the same target of t1 (race condition).
TL;DR
Never create a thread using another thread instance (even though it implements Runnable). Instead create a separate Runnable and pass it:
final Runnable run = new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
Thread t1 = new Thread(run, "t1");
Thread t2 = new Thread(run, "t2"); //new Thread(t1, "t2"); is incorrect!
t1.start();
t2.start();
You don't need any join()s here, by default these are non-daemon threads.
See also
Java Threading Basics (discussion on #2)
Add before t2.start();:
System.out.println("t1 is alive: " + t1.isAlive());
If main thread is waiting for t1 to die then t2.start() can not run t1's run method. Otherwise, without waiting for t1 to die, t2 can run t1's run method.
This is because main thread waits for t1 to die when you call t1.join().
And when you do this
Thread t2 = new Thread(t1);
you are passing t1 as target object whose run method is called.
How can I make a thread run only if the other thread is running too, meaning, if I return from run in one thread, then I want the other to stop running too,
my code looks something like this:
ClientMessageHandler clientMessagehandler = new ClientMessageHandler();
ServerMessageHandler serverMessagehandler = new ServerMessageHandler();
Thread thread1 = new Thread(serverMessagehandler);
Thread thread2 = new Thread(clientMessagehandler);
thread2.start();
thread1.start();
I want to cause thread1 to stop running when thread2 stops running.
edit: detecting when thread2 stops running in order stop thread1 from running, and not how to stop thread1 from running
thanks
This minimal example should demonstrate the basic idea:
import java.io.*;
import java.util.concurrent.LinkedBlockingQueue;
public class Test {
static LinkedBlockingQueue<String> msgBuf = new LinkedBlockingQueue<String>();
static volatile boolean keepRunning = true;
static Thread thread1, thread2;
public static void main(String[] args) throws IOException {
ClientMessageHandler clientMessagehandler = new ClientMessageHandler();
ServerMessageHandler serverMessagehandler = new ServerMessageHandler();
thread1 = new Thread(serverMessagehandler);
thread2 = new Thread(clientMessagehandler);
thread2.start();
thread1.start();
}
}
class ClientMessageHandler implements Runnable {
public void run() {
while (Test.keepRunning) {
try {
String msg = Test.msgBuf.take();
System.out.println("Eating " + msg);
} catch (InterruptedException ie) {
}
}
}
}
class ServerMessageHandler implements Runnable {
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String in;
try {
while (!(in = br.readLine()).equals("quit")) {
System.out.println("Feeding " + in);
Test.msgBuf.offer(in);
}
} catch (IOException e) {
}
Test.keepRunning = false;
Test.thread2.interrupt();
}
}
Edit for question clarification
I see two immediate options:
Option 1. Have the ClientMessageHandler implementation terminate the ServerMessageHandler as it terminates. This means the client needs a reference to the server thread.
public class ClientMessageHandler implements Runnable {
Thread serverThread;
public ClientMessageHandler(Thread srvThread) {
this.serverThread = srvThread;
}
public void run() {
try {
while (true) { ... }
} finally {
serverThread.interrupt();
}
}
}
Option 2. Use thread2.join() or a CountDownLatch to wait for thread2 to terminate. When control returns from the join (or CountDownLatch#await()).
ClientMessageHandler clientMessagehandler = new ClientMessageHandler();
ServerMessageHandler serverMessagehandler = new ServerMessageHandler();
Thread thread1 = new Thread(serverMessagehandler);
Thread thread2 = new Thread(clientMessagehandler);
thread2.start();
thread1.start();
thread2.join(); //blocks until the client terminates
thread1.interrupt();
Make sure that inside thread1's run method, you have some logical place where you can check the interrupt status (Thread#isInterrupted()) and decide to terminate. Also, you must take care to handle InterruptedException properly and either terminate or reset the interrupt flag.
A Thread will only stop when the run() method returns. The Thread#interrupt() only signals that a request for interruption has made. You still have to write the code in run() method accordingly that it periodically checks Thread#isInterrupted() and handle accordingly. E.g. check for it on every unit of task the Thread is doing, or on every certain progress when sort of progresslistener is attached.