06. maj 2003 - 10:47
Der er
15 kommentarer og
2 løsninger
Tråde i java
Følgende kode sender kun hver 3. mail - hvad er det jeg gør forkert?
for (int i = 0; i < mailRecievers.length; i++) {
if ( i % 3 == 1) {
System.out.println("Sleeping 5 sec ...");
Thread.sleep(5000);
}
final int soFar = i;
new Thread( ) {
public void run( ) {
try {
FileOutputStream mailMessage.setRecipient(Message.RecipientType.TO, mailRecievers[soFar]);
mailTrans.send(mailMessage);
} catch (Exception e) {
System.out.println("Error while sending, " + e.getMessage());
}
}
}.start();
}
Gæt:
soFar når at ændre sig inden tråden bruger den.
Prøv med:
for (int i = 0; i < mailRecievers.length; i++) {
if ( i % 3 == 1) {
System.out.println("Sleeping 5 sec ...");
Thread.sleep(5000);
}
MailSender ms = new MailSender(mailReceivers[i]);
ms.start();
}
class MailSender extends Thread {
private String receiver;
public MailSender(String receiver){
this.receiver = receiver;
}
public void run( ) {
try {
FileOutputStream mailMessage.setRecipient(Message.RecipientType.TO, receiver);
mailTrans.send(mailMessage);
} catch (Exception e) {
System.out.println("Error while sending, " + e.getMessage());
}
}
Hmmm - jeg får stadig ikke sendt alle mine mails, det virker som om tråden overtages af ny udsending ....
Måske er det mailTrans der har et multithreaded problem.
Prøv og opret et ny objekt i hver tråd.
Prøv eventuelt at vende din for løkke, således at den tæller ned i stedet for, brug derefter setPriority(i) på tråden, så vil en ny tråd ikke overtage får tråden "i" er død.
Husker du at lave din kode trådsikker? Det er et komplekst emne i teorien, men lav klassen syncronized så har du ikke problemer med din kritiske sektion (dvs. variablerne i klassen).
JP
PRøv at bruge arne_v's kode og i run metoden på MailSender klassen, indsætter du
System.out.println("Sending mail to: " +this.receiver);
Så får du da trods alt at vide om den prøver at sende, og ved dermed om problemet er i mailTrans.
Jeg har en masse System.out.println og de viser såmænd det jeg forventer.
Som koden ser ud nu, har jeg oprettet en klasse hvori der kun findes en funktion, der i en tråd sender en mail ud. Funktionen modtager en Mimemessage og en adresse.
Denne funktion kaldes i en for løkke, problemerne lige nu er,
1) at den ikke sender det forventede antal mails.
2) indholdet af mailen, (som pt. er counteren fra for løkken) ... virker lidt tilfældig.
Det ser jo ud som om jeg giver tråden et nyt kald førend den har behandlet det første kald.
Klassen :
******************************
class MailSender {
public void send( String adr, MimeMessage message ) {
final String thisAdr = adr;
final MimeMessage myMessage = message;
new Thread( ) {
public void run( ) {
try {
myMessage.addRecipient(javax.mail.internet.MimeMessage.RecipientType.TO, new InternetAddress(thisAdr));
Properties props = new Properties();
props.put("mail.smtp.host", "localhost");
Session sendMailSession;
sendMailSession = Session.getInstance(props, null);
Transport transport;
transport = sendMailSession.getTransport("smtp");
transport.send(myMessage);
} catch (Exception e) { System.out.println("Udsending fejlede " + e.getMessage()); }
}
}.start();
}
}
Koden som kalder klassen
*******************************************
Vector myMails = new Vector();
Vector myInts = new Vector();
for (int i = 0; i < mailRecievers.length; i++) {
if ( i % 3 == 1) {
System.out.println("Sleeping 5 sec ...");
Thread.sleep(5000);
}
String tmpStr = "Du er " + i;
message.setText(tmpStr);
MailSender ms = new MailSender();
myMails.add(ms);
Integer myInt = new Integer(i);
myInts.add(myInt);
System.out.println(myInt);
ms.send(mailRecievers[myInt.intValue()].getAddress(), message);
}
De to Vectorer er der fordi jeg tænkte jeg mistede referencen til counteren (i) i for- løkken og måske også MailSender objektet.
Adresselisten indeholder 5 stk ( ens ).
indholdet af mail 1 er Du er 0
indholdet af mail 1 er Du er 3
indholdet af mail 1 er Du er 4
ja, mailTrans kunne meget vel være problemet ......
Prøv og erstat:
final String thisAdr = adr;
final MimeMessage myMessage = message;
med:
final String thisAdr = (String)adr.clone();
final MimeMessage myMessage = (MimeMessage)message.clone();
Hmmm - jeg har nu fået det til at køre med følgende kode :
Koden:
*****************************
final MimeMessage thisMessage = message;
for (int i= (mailRecievers.length-1); i != -1; i--){
if (i%5 == 1) {
Thread.sleep(5000);
System.out.println("Sleeping ... ");
}
final String tmpAdr = mailRecievers[i].getAddress();
new Thread( ) {
public void run( ) {
MailSenderII mailor = new MailSenderII(tmpAdr,thisMessage);
mailor.send();
}
}.start();
}
Klassen
*************************************
class MailSenderII {
private InternetAddress mailAdress;
private MimeMessage message;
private Properties props = new Properties();
private Session sendMailSession;
Transport transport;
public MailSenderII(String adr, MimeMessage msg) {
this.message = msg;
props.put("mail.smtp.host", "localhost");
sendMailSession = Session.getInstance(props, null);
try {
this.mailAdress = new InternetAddress(adr);
message.setRecipient(javax.mail.internet.MimeMessage.RecipientType.TO,this.mailAdress);
transport = sendMailSession.getTransport("smtp");
} catch (Exception e) { System.out.println("Ehhh noget fejlede HER"); }
}
public void send() {
try {
transport.send(message);
} catch (Exception e) { System.out.println("Gejl" + e.getMessage()); }
}
}
Det så ud til at det skyldtes stumpen hvor jeg udskifter noget af teksten :
String tmpStr = "Du er " + i;
message.setText(tmpStr);
Nu jeg tænker over det, er det vel logisk nok ....
Stor tak herfra, i fik mig pisket omkring nogle ideer der endte i en løsning :-)
Jeg fordeler pointsene mellem jer.
Hmmm - ikke alle er mulige at give points, for jpvj, du var inde på noget af det rigtige.
Beklager :-(
Hvorfor er det at du ikke bare sikrer din kode, så den er reentrant? Så slipper du for at tænke så meget :-)
Kurser inden for grundlæggende programmering