2

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

任何建议将不胜感激。

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

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

3 回答 3

5

您应该在两个线程都可以访问的对象上同步您的方法,因为现在您正在使用您所在的对象实例来同步哪个原因永远不会产生影响,因为据我所知,两个线程都只停留在它们的范围内你的问题。您可以在创建时将一个简单的对象传递给两个线程,然后像这样重新格式化您的方法

传递对象进行同步:

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
   }
}
于 2012-11-13T16:07:40.573 回答
3

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

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

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

于 2012-11-13T16:07:52.370 回答
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 的实例并将其传递给您的线程。

于 2012-11-13T15:52:05.337 回答