Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Synchronized method...not synchronized

For my current java exercise, I have to get mail from 2 different gmail accounts. I have done this by creating new instances of my gmail class. The gmail class extends thread, and within it there is a synchronized method readMail() which gets the mail and prints it. This readMail method is called by the run method in a while(true) loop, and then it sleeps for 30 seconds, the idea being that it gets mail every 30 seconds. However, the synchronized method does not seem to work. The threads interrupt each other and the method does not print all the items of a message before the other thread interrupts and starts printing.

Any advice would be greatly appreciated.

Please see the method below that is causing me trouble:

public synchronized void readMail() throws MessagingException, IOException {
    Folder inbox = store.getFolder("Inbox");
    inbox.open(Folder.READ_ONLY);
    messages = inbox.getMessages();
    // System.out.println("No of Messages : " + inbox.getMessageCount());
    // System.out.println("No of Unread Messages : "
    // + inbox.getUnreadMessageCount());

    for (int i = 0; i < inbox.getUnreadMessageCount(); i++) {

        System.out
                .println("*****************************************************************************");
        System.out.println("NEW MESSAGE " + (i + 1) + ":");
        msg = messages[i];
        // System.out.println(msg.getMessageNumber());
        // Object String;
        // System.out.println(folder.getUID(msg)

        String subject = msg.getSubject();

        System.out.println("Subject: " + subject);
        System.out.println("From: " + msg.getFrom()[0]);
        System.out.println("To: " + msg.getAllRecipients()[0]);
        System.out.println("Date: " + msg.getReceivedDate());
        System.out.println("Size: " + msg.getSize());
        // System.out.println(msg.getFlags());
        // System.out.println("Body: \n"+ msg.getContent());
        // System.out.println(msg.getContentType());
    }
}

Then the run method:

    public void run() {
    while (true) {

        try {
            readMail();
        } catch (MessagingException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        try {
            sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
}
like image 802
Programatt Avatar asked Nov 16 '25 14:11

Programatt


2 Answers

you should synchronize your method on an object both threads have access to, because right now you are using the object instance you are in to synchronize which of cause will never have an effect because both Threads only stay inside their on scope as far as I understand your question. You could pass an simple Object to both threads at their creation and reformat your method like this

passing object to synchronize:

public static void main(String[] args){
     Object obj = new Object();
     gmail g1 = new gmail(obj);
     gmail g2 = new gemail(obj);
     // more code
}

save reference in gmail class:

public class gmail extends Thread{
    private Object sharedObject;

    public gmail( Object synchronizer){
          sharedObject = synchronzier;
    }

synchronize on it:

public void readMail(){
   synchronized( sharedObject ){
       // your method code goes here
   }
}

For this Example synchronizing on the class object of gmail is also possible and is even more easy

public void readMail(){
   synchronized( this.getClass() ){
       // your method code goes here
   }
}
like image 166
Lesstat Avatar answered Nov 19 '25 05:11

Lesstat


When you synchronize readMail() as a method, then only one thread at a time can access the Objects readMail() method. If you have two different object instances of type GMail with a readMail() method, two threads can access them both unsynchronized (in parallel).

In other words, the semaphor that block execution of the readMail() method is in fact the GMail object. With two different object instances, you have two semaphores which do not interact.

It would work if you had only one instance of a GMail object with a synchronized readMail() method. Then only one thread at a time could access it.

like image 37
Udo Klimaschewski Avatar answered Nov 19 '25 06:11

Udo Klimaschewski