Wait for mail sending in another thread to complete - java

I've got a problem I can't really figure out. I have my main thread, and in it I want to
Send an email with an attachment
Delete the files that were attached
in that order. My problem is that I am using an email helper that I don't have control over, and it generates another thread that does the sending. Because of this, my files are being deleted before they are done being attached, and I am getting a FNF error in the mailer. I am looking to find a way to make my main thread wait until the files are done being attached. I don't know how long that will take. I don't have control over the other thread creation, so I can't use join(). Is there something I can use with Transport maybe, or a way to wait for all threads made in a method/class to stop?
The layout of my program is
//do stuff
MailHelper.sendMail(...); //thread is created somewhere in this method
deleteFiles(); //this happens before sendMail is finished!
I need to use Java 6. Worst-case I can have my main thread sleep for a few seconds, but that's unideal. Any help is appreciated

This is an interesting question! Basically you want to wait for all child threads to complete, but have no control over them.
Here is a demonstration of the technique using ThreadGroup:
Assuming you have a MailHelper class like this:
public class MailHelper {
public void sendMail(){
Thread t = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("MailHelper: Sending mail for 6s");
for(int i = 0; i < 6; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(".");
}
System.out.println("MailHelper: Sent mail!");
}
});
t.start();
}
}
then our Main class demonstrates how use it:
public class Main {
public static void main(String[] args) throws InterruptedException {
final MailHelper mh = new MailHelper();
ThreadGroup mailThreadGroup = new ThreadGroup("mailGroup");
Thread callSendmailThread = new Thread(mailThreadGroup, new Runnable() {
#Override
public void run() {
System.out.println("Calling sendMail().");
mh.sendMail();
System.out.println("sendMail() returned.");
}
});
callSendmailThread.start();
callSendmailThread.join();
System.out.println("callSendmailThread joined. Waiting for rest of ThreadGroup to finish.");
// We cannot rely on ThreadGroup.activeCount() to give us an accurate number, and it could be zero!
Thread[] mailThreads = new Thread[mailThreadGroup.activeCount() + 1];
//Therefore retry enumerate until our array was large enough to hold all
while ( mailThreadGroup.enumerate( mailThreads, true ) == mailThreads.length ) {
mailThreads = new Thread[ mailThreads.length * 2 ];
}
for(Thread t : mailThreads){
if(t != null && t.isAlive()){
System.out.println("Joining thread " + t.getName());
t.join();
System.out.println("Thread " + t.getName() + " joined.");
}
}
mailThreadGroup.destroy();
System.out.println("Done!");
}
}
The output:
Calling sendMail().
sendMail() returned.
callSendmailThread joined. Waiting for rest of ThreadGroup to finish.
Joining thread Thread-1
MailHelper: Sending mail for 6s
.
.
.
.
.
.
MailHelper: Sent mail!
Thread Thread-1 joined.
Done!
Note that you must ensure that the Thread-1 is actually started by the time you enumerate the ThreadGroup, thus joining the callSendMailThread is absolutely necessary. Otherwise you'd get a race condition.
Also note that the quirky behaviour of ThreadGroup.enumerate() must be accounted for, by retrying to enumerate all the items several times.

The easy way to solve the issue logically is to track if the mail is send sucessfully.
It can be done by any of the below
1) Set a global variable with some value after mail is send from other thread and reset it value once the attachement is deleted.
2) Instead of variable you can also try creating a file.
Thank you,
Mukeshkoshym

Related

notifyAll() not awakening processes

I'm programming a little Java program where I need to create threads (philosophers in my code), and these philosophers need to change of state between thinking, hungry and eating.
I'm not that far into the project and I have the next problem:
public class NewMain {
static Philosopher [] p;
public static void main(String[] args) {
p = new Philosopher[5];
p[0] = new Philosopher(0);
p[1] = new Philosopher(1);
p[2] = new Philosopher(2);
p[3] = new Philosopher(3);
p[4] = new Philosopher(4);
for (int i = 0; i<5; i++) {
try{
p[i].run();
if(i == 4) {
p.notifyAll();
}
}
catch(IllegalMonitorStateException e) {}
}
}
}
I'm creating 5 philosophers(threads). Each one of those has a wait() instruction in their code:
#Override
public void run() {
int rand;
if (status == 0) {
System.out.println("Philosopher " + id + " is waiting.");
try {
wait();
System.out.println("Awoken");
while(status == 0) {
System.out.println("Philosopher " + id + " is thinking.");
sleep(100);
rand = ThreadLocalRandom.current().nextInt(0,100);
if(rand > 95){
status = 1;
System.out.println("Philosopher " + id + " changed state to hungry.");
}
}
}
catch(InterruptedException e) {
System.out.println("Error!");
}
catch(IllegalMonitorStateException e) {}
}
}
The problem is that when invoking notifyAll(), the processes don't awake and they just die after executing the run() method of each thread.
If anyone is wondering, I'm not using synchronized because I need to run the methods at the same time.
Also, I've tried to put notifyAll() inside the run() method of the threads.
Can anyone tell me what's going on and why are the threads not continuing
with their code?
Problems
notify[All]() and wait() should be used on the same instance. You are notifying on the array Philosopher[] p, but waiting on this which is a Philosopher. It's like I am waiting for you, but you are notifying Sarah that you're going to be late.
You have created the threads but haven't started them properly. Calling run will execute the method in the current thread. Use the method start instead. It begins execution concurrently.
To use x.notify[All]() or x.wait(), you have to be within a synchronised block synchronized(x) { ... }. Ignoring IllegalMonitorStateException won't help you at all.
Answers
... why are the threads not continuing with their code?
They might call wait after the 4th thread notifies them.
... the processes don't awake and they just die ...
They don't die, they still wait until you terminate the program.
I'm not using synchronizedbecause I need to run the methods at the same time
You need to run the methods at the same time correctly, right? Here, synchronisation is required at least for building wait-notify communication.
p is an array of Runnable. when you write
p[i].run();
Then, you are invoking run method (actually you haven't started a thread here instead called run method) using object stored at p[i] location. Now, as per notifyAll
Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods.
You should have used start() instead run() to start a new thread.
notify() and notifyAll are used when thread(s) are waiting to acquire monitor on current object.

multi-thread run processes simultaneously

I am currently interested in learning about Multi-threading. I have written a piece of code. And my question is if this the correct way. I later want to implement this in another code of mine. My idea was to run multiple threads existing of the same class. So let's say 5 threads and they all have a runner class inside them. What I want to implement in another code, is that I want to run multiple browsers at once. So, I have a class Browser. And then I have 5 threads with the class Browser. And they are all working simultaneously but don't know each other, so they don't have any interaction with each other at all.
So is this idea OK then?
class Runner implements Runnable {
public void run() {
for(int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class BasisDemo {
public static void main(String[] args) {
Thread runner1 = new Thread(new Runner(), "Runner 1");
runner1.start();
Thread runner2 = new Thread(new Runner(), "Runner 2");
runner2.start();
}
}
Is this a good practise and does it support my idea?
Or is using multi-threading even unnecessary.
I don't know it for sure.
Thanks for helping me out.
So your idea would work. If you try this code below.
System.out.println(System.currentTimeMillis());
System.out.println(System.currentTimeMillis());
You will find that the time is actually the same, which mean these two lines are executed almost at the same time.
In term of your code:
Thread runner1 = new Thread(new Runner(), "Runner 1");
runner1.start();
Thread runner2 = new Thread(new Runner(), "Runner 2");
runner2.start();
These threads will be executed at almost the same time, that's why your idea will work.
To make it more accurate. You can switch your codes:
Thread runner1 = new Thread(new Runner(), "Runner 1");
Thread runner2 = new Thread(new Runner(), "Runner 2");
runner1.start();
runner2.start();
If you want to make the timing even more accurate. You can use CyclicBarrier. It allows a set of thread to wait for each other and start at the same time. Here is demo codes:
class Demo {
final CyclicBarrier barrier;
class Broswer implements Runnable {
Worker() { }
public void run() {
while (!done()) {
try {
// wait for other threads
barrier.await();
// work for something, in your case an hour, but how can you control that
// work....
// sleep for a certain time
sleep(certain time)
} catch (InterruptedException ex) {
return;
} catch (BrokenBarrierException ex) {
return;
}
}
}
}
public static main(String args[]) {
barrier = new CyclicBarrier(N);
for (int i = 0; i < N; ++i)
new Thread(new Broswer()).start();
// wait until all done, in your case, forever.
}
}
Sounds like you're on the right track. Each thread will have no reference of each other, since you defined them as separate objects. They would both be able to contain their own data, execute their own methods, completely independently of one another.
One way you could confirm they are executing simultaneously is to make your loop start from a random number, that way you will see the console output incrementing beginning from two different numbers. (i.e. 100, 50, 101, 102, 51, 52, ...)
What you have outlined is the most common way to create threads in Java, you can read more about it here if you have questions later on.
1 Thread, not 5
Or is using multi-threading even unnecessary. I don't know it for sure.
If using the same class to do the same work, then No, no need for 5 threads. You only need one thread to run a task daily in the background.
If you want a copy everyday of a daily newspaper, would you send one of you children to the store with a dollar in hand each morning or would you send five of your children each with a dollar in hand?
ScheduledExecutorService
Also, Java provide a slick facility for this kind of work where you are scheduling tasks to be done in the background regularly: ScheduledExecutorService. Search Stack Overflow for more info, and read the Oracle Tutorial on Executors.

synchronized thread execution

my task is to create thread in this order: if A start->start B and C, if B start->start D.
And destroy them in reverse order If D then B. If B and C then A. I hope you get it. I manage to do it but I guess there is better way to do it. Do you have any suggestions?
After your comments i have changed my code and it is much more simply. But now it looks "stupid". I would like to change hardcore of if statements and implementation, any advice? tnx for advice I'm learning with you.
This is my new code:
import java.util.*;
class RobotController implements Runnable{
String name;
public void run() {
Thread t = Thread.currentThread();
System.out.println(t.getName() + " status = " + t.isAlive());
System.out.println(t.getName() + " status = " + t.getState());
}
public static void main(String args[]) throws InterruptedException{
Thread thread_A = new Thread(new RobotController(), "Thread A");
Thread thread_B = new Thread(new RobotController(), "Thread B");
Thread thread_C = new Thread(new RobotController(), "Thread C");
Thread thread_D = new Thread(new RobotController(), "Thread D");
thread_A.start();
thread_A.join();
System.out.println(thread_A.getState());
thread_B.start();
thread_B.join();
System.out.println(thread_B.getState());
thread_C.start();
thread_C.join();
System.out.println(thread_C.getState());
thread_D.start();
System.out.println(thread_D.getState());
}
}
There are some flaws in your code which will make it not to work accordingly sometimes:
You called thread_A.start() and then checked thread_A.isAlive(). Now what if , thread_A is already completed before thread_A.isAlive() condition is checked?.thread_B and thread_C is never started. Your application fails.
Assume that thread_A is not completed and thread_A.isAlive() condition is passed, then starting of thread_B before thread_C is not always guaranteed by Java thread scheduler. Again your application fails.
Assume that thread_B starts before thread_C and if thread_B completes before thread_B.isAlive() is checked then the if condition fails and thread_D is never started. Again your application fails.
Now a point to ponder:
There is no need to check if the thread is alive after its join() method is called. It is an unnecessary runtime overhead.
EDIT
OK, Here is the modified version of code..I hope it would let you understand the dynamics of thread:
class RobotController implements Runnable
{
private final Object lock = new Object();
private void notifyThread()
{
synchronized(lock)
{
lock.notify();
}
}
public void run()
{
synchronized(lock)
{
try
{
System.out.println(Thread.currentThread().getName() + " started");
lock.wait();
System.out.println(Thread.currentThread().getName()+ " stopped");
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
public static void main(String args[]) throws InterruptedException
{
RobotController rca = new RobotController();
RobotController rcb = new RobotController();
RobotController rcc = new RobotController();
RobotController rcd = new RobotController();
Thread thread_A = new Thread(rca,"Thread A");
Thread thread_B = new Thread(rcb,"Thread B");
Thread thread_C = new Thread(rcc,"Thread C");
Thread thread_D = new Thread(rcd,"Thread D");
thread_A.start();
while (thread_A.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
thread_B.start();
thread_C.start();
while (thread_B.getState() != Thread.State.WAITING && thread_C.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
thread_D.start();
while (thread_D.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
rcd.notifyThread();
thread_D.join();
rcc.notifyThread();
thread_C.join();
rcb.notifyThread();
thread_B.join();
rca.notifyThread();
}
}
And here is the output:
Thread A started
Thread B started
Thread C started
Thread D started
Thread D stopped
Thread C stopped
Thread B stopped
Thread A stopped
In multi threading, there is no need of synchronization unless the common data is shared by multiple threads.
In your case, you want to start and stop the threads in a particular order. For this, there is join method in Thread class. This link shows good example of join method.
In my opinion, it is quite strange to use synchronized (lock) in your run method to lock your object. The reason is that in each Thread object has the different lock attribute, which is belong to each object. It means you are trying to lock the different objects. Actually, it doesn't make sense.
Basically, the object that you should apply the synchronized are any shared objects. For example, you need to count something and then you create a class object to share it in your class. In this case, it should be locked while being read or written.
I would like to highlight two points here:
Have a look at thread execution life cycle here. It says that, when start() method is called, thread enters in runnable state and not in running state. When thread enters in running state, that means run() method is getting exexuted. CPU/OS decides the priority of which thread should be transferred from runnable to running thread. E.g. if you call start() method for 4 threads, it is not necessary that they will execute in that particular order. (Running the same program in my pc multiple times gives me different outputs.
In your case, when the condition if(thread_A.isAlive()) is executed, it is possible that the thread A may not be in running state. Hence, the control will not go into if which is not correct.
To correct this behavior, in main, a while loop should implemented which waits until the thread becomes alive and so on.
2 . In your program, you have not assigned names to the threads and you are printing the name in the run() method. In this case, JVM assigns the names to threads in order of their execution e.g. first thread to execute will have name as 'Thread-0' and so on. Hence, we will not be able to identify which thread executed first. Assign the names using setName() method.

how can i make a thread sleep for a while and then start working again?

I have the following code:
public void run()
{
try
{
logger.info("Looking for new tasks to fetch... ");
// definitions ..
for(Task t: tasks)
{
logger.info(" Task " + t.getId() + " is being fetched ");
// processing ... fetching task info from db using some methods
}
Thread.sleep(FREQUENCY);
//t.start();
} catch (Exception e)
{
logger.info("FetcherThread interrupted: "+e.getMessage());
}
}
I'm trying to make the thread to sleep for a specific time "FREQUENCY" and then work again. when I execute this code in eclipse, the thread works only once and then nothing happens and process terminates. If I remove the comment from the statement: t.start(), I get "FetcherThread interrupted: null".
Can anyone tell me where I'm going wrong?
N.B.: I want the thread to be working all the time, but fetching on periods (say every 5 minutes)
You're missing any sort of loop in that code.
It seems that the thread is actually doing what you tell it to do: it runs all the tasks, then sleeps for a bit - then it has no more work to do, and so exits. There are several ways to address this, in ascending order of complexity and correctness:
The simple (and naive) way to address this is to wrap the try-catch block in an infinite loop (while(true) { ... }). This way after the thread finishes sleeping, it will loop back to the top and process all the tasks again.
However this isn't ideal, as it's basically impossible to stop the thread. A better approach is to declare a boolean field (e.g. boolean running = true;), and change the loop to while(running). This way, you have a way to make the thread terminate (e.g. expose a method that sets running to false.) See Sun's Why is Thread.stop() deprecated article for a longer explanation of this.
And taking a step further back, you may be trying to do this at too low a level. Sleeping and scheduling isn't really part of the job of your Runnable. The actual solution I would adopt is to strip out the sleeping, so that you have a Runnable implementation that processes all the tasks and then terminates. Then I would create a ScheduledExecutorService, and submit the "vanilla" runnable to the executor - this way it's the job of the executor to run the task periodically.
The last solution is ideal from an engineering perspective. You have a class that simply runs the job once and exits - this can be used in other contexts whenever you want to run the job, and composes very well. You have an executor service whose job is the scheduling of arbitrary tasks - again, you can pass different types of Runnable or Callable to this in future, and it will do the scheduling bit just as well. And possibly the best part of all, is that you don't have to write any of the scheduling stuff yourself, but can use a class in the standard library which specifically does this all for you (and hence is likely to have the majority of bugs already ironed out, unlike home-grown concurrency code).
Task scheduling has first-class support in Java, don't reinvent it. In fact, there are two implementations: Timer (old-school) and ScheduledExecutorService (new). Read up on them and design your app aroud them.
Try executing the task on a different thread.
You need some kind of loop to repeat your workflow. How shall the control flow get back to the fetching part?
You can put the code inside a loop.( May be while)
while(condition) // you can make it while(true) if you want it to run infinitely.
{
for(Task t: tasks)
{
logger.info(" Task " + t.getId() + " is being fetched ");
// processing ... fetching task info from db using some methods
}
Thread.sleep(FREQUENCY);
}
Whats happening in your case its running the Task loop then sleeping for some time and exiting the thread.
Put the thread in a loop as others have mentioned here.
I would like to add that calling Thread.start more than once is illegal and that is why you get an exception.
If you would like to spawn multiple thread create one Thread object per thread you want to start.
See http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#start()
public void run()
{
while (keepRunning) {
try
{
logger.info("Looking for new tasks to fetch... ");
// definitions ..
for(Task t: tasks)
{
logger.info(" Task " + t.getId() + " is being fetched ");
// processing ... fetching task info from db using some methods
t.start();
}
Thread.sleep(FREQUENCY);
} catch (Exception e) {
keepRunning = false;
logger.info("FetcherThread interrupted: "+e.getMessage());
}
}
}
Add a member call keepRunning to your main thread and implement an accessor method for setting it to false (from wherever you need to stop the thread from executing the tasks)
You need to put the sleep in an infinite loop (or withing some condition specifying uptill when you want to sleep). As of now the sleep method is invoked at the end of the run method and behavior you observe is correct.
The following demo code will print "Sleep" on the console after sleeping for a second. Hope it helps.
import java.util.concurrent.TimeUnit;
public class Test implements Runnable {
/**
* #param args
*/
public static void main(String[] args) {
Test t = new Test();
Thread thread = new Thread(t);
thread.start();
}
public void run() {
try {
// logger.info("Looking for new tasks to fetch... ");
// definitions ..
// for(Task t: tasks)
// {
// logger.info(" Task " + t.getId() + " is being fetched ");
// // processing ... fetching task info from db using some methods
// }
while (true) { // your condition here
TimeUnit.SECONDS.sleep(1);
System.out.println("Sleep");
}
// t.start();
} catch (Exception e) {
// logger.info("FetcherThread interrupted: "+e.getMessage());
}
}
}
You could try ScheduledExecutorService (Javadoc).
And us it's scheduleAtFixedRate, which:
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.

how to do Timer task in java

I just want to implement the following in Java , Do anyone have some idea..?
public String method1(){
//statement1
.
.
.
//statement 5
}
I want to set a timer for the statemen1 ( which involves some network communication ) . If the statement1 is not getting finished even after 25seconds , the control should go to statement 5 . how can I implement this in java ..?
You can make use of the java.util.TimerTask.
extend TimerTask and over-ride the run() method.
What you put in the run method is what should be executed every 25 seconds.
To start the timer do the following:
Timer tmer = new Timer("Network Timer",false);
ExtendedTimerTask extdTT = new ExtendedTimerTask(<params_go_here>)
tmer.schedule(extdTT,25000,25000);
You can parse the object which does the networking part at <params_go_here> and assign to a local variable in your ExtendedTimerTask.
When the timer executes you can do the necassary calls on your <params_go_here> object to see if its finished.
Please note that the checker will run in a seperate thread as java.util.TimerTask implements java.util.Runnable
Cool
You could do something like this:
private volatile Object resultFromNetworkConnection;
public String method1(){
resultFromNetworkConnection = null;
new Thread(){
public void run(){
//statement1
.
.
.
// assign to result if the connection succeeds
}
}.start();
long start = System.currentMilis();
while (System.currentMilis() - start < 25 * 1000) {
if (resultFromNetworkConnection != null) break;
Thread.sleep(100);
}
// If result is not null, you can use it, otherwise, you can ignore it
//statement 5
}
If there is no time-out parameter for the blocking method at statement1, you would have to put statement1 in a separate thread, then wait(25000) for it to finish, if the wait times-out, you go ahead with statement 5 and ignore the result of the blocking call.
I/O operations (including network communication) are synchronous. So you can configure a timeout for the particular network communication, and you will have the desired behaviour. How exactly to configure the timeout - depends on what you are using.
You mention network communication, so I'll give a rough example with an InputStream from a Socket with a timeout set that may apply to other classes. While you could make timer threads, this is simpler.
socket.setSoTimeout(25 * 1000);
try
{
data = readMyData(socket.getInputStream());
doStuff(data);
}
catch(SocketTimeoutException e){ }
doStatement5();
Here's is a pattern that you can use. The idea is to start a separate thread to do the network stuff. The "main" thread will wait for the adequate time and check a shared variable that indicates if the networking stuff did his job on time.
public class TestConstrainNetworkOP {
private Object lock = new Object();
private Object dataAvailable;
private Object constrainedNetworkOp() throws InterruptedException {
Thread t = new Thread(new DoTask());
t.start();
Thread.sleep(25000);
synchronized (lock) {
if (dataAvailable != null) {
//the data arrived on time
}
else{
//data is not available and
//maybe throw a timeoutexception
}
}
}
public class DoTask implements Runnable {
#Override
public void run() {
// do the networking
synchronized (lock) {
// save your data here
dataAvailable = new Long(1);
}
}
}
}
This is a useful pattern if you don't too much control over the network layer (e.g. RMI, EJB). If you are writing the network communication by yourself, then you can set the timeout direct to the socket (as people previously said) or use Java NIO

Categories

Resources