سؤال

I've got a problem I can't really figure out. I have my main thread, and in it I want to

  1. Send an email with an attachment
  2. 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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top