Java同步方法...未同步

时间:2012-11-13 15:49:44

标签: java synchronized

对于我目前的java练习,我必须从2个不同的Gmail帐户获取邮件。我通过创建我的gmail类的新实例来完成此操作。 gmail类扩展了线程,在其中有一个同步方法readMail(),它获取邮件并打印它。这个readMail方法由run方法在while(true)循环中调用,然后它休眠30秒,这个想法是它每30秒获取一次邮件。但是,synchronized方法似乎不起作用。线程互相中断,在另一个线程中断并开始打印之前,该方法不会打印消息的所有项目。

非常感谢任何建议。

请参阅下面给我带来麻烦的方法:

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());
    }
}

然后运行方法:

    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();
        }
    }
}
}

3 个答案:

答案 0 :(得分:5)

你应该在两个线程都可以访问的对象上同步你的方法,因为你现在正在使用你所在的对象实例同步哪个原因永远不会有效,因为两个线程只保留在它们的on范围内据我了解你的问题。您可以在创建时将一个简单的Object传递给两个线程,并像这样重新格式化您的方法

传递对象以进行同步:

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

在gmail类中保存引用:

public class gmail extends Thread{
    private Object sharedObject;

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

同步:

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

对于这个例子,同样可以在gmail的类对象上进行同步,并且更加容易

public void readMail(){
   synchronized( this.getClass() ){
       // your method code goes here
   }
}

答案 1 :(得分:2)

synchronized关键字用于线程调用的方法,而不是线程中的方法。

因此,您的线程中定义的readMail方法必须调用其他方法所有线程使用的方法,并在其他位置定义,并同步那个方法。

所以创建一个类

public class MailHelper {
   public static void synchronized doRead(store) throws MessagingException, IOException {
       // all your readMail code here, except pass in the store
   }
}

并在你的线程类中

public void readMail() throws MessagingException, IOException {
    // get your store
     MailHelper.doRead(store);
}

请注意,您可以使MailHelper上的方法不是静态的,然后您必须创建MailHelper的实例并将其传递给您的线程。

答案 2 :(得分:2)

将readMail()同步为方法时,一次只有一个线程可以访问 Objects readMail()方法。如果您有两个不同的GMail类型的对象实例和一个readMail()方法,则两个线程可以同时访问它们(并行)。

换句话说,阻止执行readMail()方法的信号实际上是GMail对象。对于两个不同的对象实例,您有两个不交互的信号量。

如果您只有一个具有同步readMail()方法的GMail对象实例,那么它将起作用。然后一次只有一个线程可以访问它。