对于我目前的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();
}
}
}
}
答案 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对象实例,那么它将起作用。然后一次只有一个线程可以访问它。