4

私はJavaの初心者で、過去にスレッドを扱ったことがありません。今、私は自分の知識レベルにとって非常にトリッキーな問題を抱えています。

「メール送信」と「メール確認」の2つの機能を開発しました。各ユーザーが自分の好みを登録すると、システムは次のような定期的な作業に関する多くの指示を含む 2 つのカタログを作成します。

A) 1500 ミリ秒ごとにメッセージを送信する

B) 1800 ミリ秒ごとにメッセージを送信する

C) 3000 ミリ秒ごとにメッセージを送信する

A) 2000 ミリ秒ごとにメッセージを確認する

B) 6000 ミリ秒ごとにメッセージを確認する

C) 8000 ミリ秒ごとにメッセージを確認する

スレッドで多くの方法を試しましたが、うまくいきません。私の質問は、それらを同期する最良の方法はどれですか? 以下は、スレッドを使用した最後の努力のコードです。

public class MailCreatorThread extends Thread {
    @Override
    public void run() {
        CreateMail(_date); //creates a mail with _date as subject
    }
}

public class GPSThread extends Thread {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (!_isTimeToStop) {
            try {
                while (_servicesToUpdate.size() == 0) {
                    Thread.sleep(500);
                }
                _currentService = (MyService) _servicesToUpdate.get(0)
                        .clone();
                _servicesToUpdate.remove(0);

                        MailCreatorThread mailCreatorThread = new MailCreatorThread();
                        mailCreatorThread.start();


            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

public class CheckServicesThread extends Thread {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (!_isTimeToStop) {
            try {
                Thread.sleep(1000);
                    for (int j = 0; j < _servicesList.length; j++) {
                        MyService currentService = ((MyService) _servicesList[j]);
                        if (myService.getTimeToNextUpdate() - 1000 <= 0) {
                            _servicesToUpdate
                                    .add((MyService) currentService
                                            .clone());
                            currentService
                                    .setTimeToNextUpdate(currentService
                                            .getUpdatePeriod());
                        } else {
                            currentService
                                    .setTimeToNextUpdate(currentService
                                            .getTimeToNextUpdate() - 1000);
                        }
                }

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        stopSelf();
    }
}
4

2 に答える 2

4

を使用して、これらのScheduledExecutorService定期的なタスクを実行できます。構文はかなり単純です。

Runnable check = new Runnable() {
    public void run() {
        checkMessage();
    }
}
Runnable send = new Runnable() {
    public void run() {
        sendMessage();
    }
}

//since what you are doing is mostly I/O you probably want to have 
//more than one thread available so that if one operation blocks,
//the other ones can be launched in parallel

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
scheduler.scheduleAtFixedRate(check, 0, 1500, MILLISECONDS);
scheduler.scheduleAtFixedRate(send, 0, 6000, MILLISECONDS);

注: Timer の javadocで説明されているように、 Ozzy の回答Timerで言及されているものは Java 1.5 で改善されているため、これ以上使用しないでください。ScheduledThreadPoolExecutor

Java 5.0 は java.util.concurrent パッケージを導入しました。その中の同時実行ユーティリティの 1 つは ScheduledThreadPoolExecutor です。これは、特定の速度または遅延でタスクを繰り返し実行するためのスレッド プールです。これは、複数のサービス スレッドを許可し、さまざまな時間単位を受け入れ、TimerTask のサブクラス化を必要としない (Runnable を実装するだけである) ため、実質的に Timer/TimerTask の組み合わせのより汎用性の高い代替品です。1 つのスレッドで ScheduledThreadPoolExecutor を構成すると、Timer と同等になります。

于 2012-04-17T18:58:36.450 に答える
3

Javaには、別のスレッドでタスクを繰り返すのに役立つ組み込みのTimerクラスとTimerTaskクラスがあります。

これにより、独自のバックグラウンドスレッドを作成するタイマーが作成されます。

Timer t = new Timer();

次に、そのタイマーに必要な数のタスクをスケジュールできます。これらのタスクは、タイマー自体のスレッドを共有します。

これは、2000ms = 2sの遅延の後、タイマースレッドで単一のタスクをスケジュールする方法です。

t.schedule(new TimerTask() {
    @Override
    public void run() {
        //task to perform
    }
}, 2000);

これは、1秒の遅延の後、タイマースレッドで繰り返されるタスクをスケジュールし、1.5秒間隔でタスクを繰り返す方法です。

t.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        //task to perform every 1.5 seconds
    }
}, 1000, 1500);

これで、両方のタスク(checkMail、sendMail)を同じタイマー(同じスレッド)にスケジュールするか、それぞれに独自のタイマー(別々のスレッド)を割り当てるかを選択できます。

詳細については、java docs(http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html)を参照してください。

お役に立てれば。

于 2012-04-17T17:42:45.860 に答える