0

3 分ごとにクラスを実行する単純な Java プログラムを作成しようとしています。これらのクラスを呼び出すために Timer と TimerTask を使用しています。

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class Receiver
{
    public static void main(String[] args)
    {
        System.out.println("Time now is -> " + new Date());

        Timer timer = new Timer();
        TimerTask task = new ReceiverTask();
        timer.scheduleAtFixedRate(task, 0, 180000);
    }
}

class DPGReceiverTask extends TimerTask
{
    private ArrayList<TaskArgs> m_tasks = new ArrayList<TaskArgs>();

    public ReceiverTask()
    {
        m_tasks.add(new TaskArgs("com.comp.Receiver", new String[] { "ARG1", "ARG2"}));
    }

    public void run()
    {
        System.out.println("Receiver Started!");

        String classpath = "D:/Receiver;D:/Receiver/lib/*";
        int i = 0;

        ArrayList<Process> processes = new ArrayList<Process>();
        for (TaskArgs task: m_tasks)
        {
            try
            {
                List<String> command = new ArrayList<String>();
                command.add(System.getProperty("java.home") + "/bin/java");
                command.add("-classpath");
                command.add(classpath);
                command.add(task.Name);

                String[] args = task.Args;
                for (String arg : args)
                {
                    command.add(arg);
                }

                Process process = new ProcessBuilder(command).start();
                processes.add(process);

            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        try
        {
            for (Process process : processes)
            {
                int exitCode = process.waitFor();
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
public class TaskArgs
{
    public TaskArgs(String name, String[] args)
    {
        Name = name;
        Args = args;
    }

    public String Name;
    public String[] Args;
}

winsw次にJavaを実行するbatファイルを実行するサービスを実装して作成しました。

receiverTask.bat

java -classpath ReceiverService.jar Receiver

receiverTask.xml

<service>
  <id>receiverTask</id>
  <name>receiverTask</name>
  <description>receiver Service</description>
  <executable>receiverTask.bat</executable>
  <logpath>D:\winsw\logs\Service</logpath>
 <log mode="roll-by-time">
  <pattern>yyyyMMdd</pattern>
    </log>
  <depend>Spooler</depend>
  <startargument>run</startargument>
  <stopargument>stop</stopargument>
</service>

この現在の実装には 2 つの問題があります。

  1. 現在の Java が終了しているかどうかに関係なく、Timer は 3 分後に別のプロセスを開始します。
  2. サービス (winsw - Java サービス ラッパー) を停止しても、java.exe または cmd.exe を実行しているプロセスは停止しません。

プロセスを強制終了するために destroy メソッドを追加しようとしましたが、これで本当によいのでしょうか?

        ...    
        try
        {
            for (Process process : processes)
            {
                Timer t = new Timer();
                TimerTask killer = new TimeoutProcessKiller(process);
                t.schedule(killer, 178000);
                int exitCode = process.waitFor();
                killer.cancel();
            }
        }

public class TimeoutProcessKiller extends TimerTask
{
    private Process p;
    public TimeoutProcessKiller(Process p)
    {
        this.p = p;
    }

    public void run()
    {
        p.destroy();
    }
}

誰か提案はありますか?

4

2 に答える 2

1

ProcessBuilder.start() を呼び出して Java アプリケーションでプロセスを開始すると、それに対する有効な Process 参照が得られ、Process クラスで destroy() メソッドを呼び出して、その特定のプロセスを強制終了できます。そのため、新しいプロセスを作成する前にリストを走査し、存在する場合は破棄する必要があります。

class DPGReceiverTask extends TimerTask {
    private ArrayList<TaskArgs> m_tasks = new ArrayList<TaskArgs>();
    private LinkedList<Process> processes = new LinkedList<Process>();

    public ReceiverTask() {
        m_tasks.add(new TaskArgs("com.comp.Receiver", new String[] { "ARG1", "ARG2"}));
    }

    public void run() {
        // shutdown prev. created processes
        for (Process process: processes) {
            process.destroy();
        }
        processes.clear();

        System.out.println("Receiver Started!");

        String classpath = "D:/Receiver;D:/Receiver/lib/*";
        int i = 0;

        for (TaskArgs task: m_tasks) {
            try {
                List<String> command = new ArrayList<String>();
                command.add(System.getProperty("java.home") + "/bin/java");
                command.add("-classpath");
                command.add(classpath);
                command.add(task.Name);

                String[] args = task.Args;
                for (String arg : args)
                {
                    command.add(arg);
                }

                Process process = new ProcessBuilder(command).start();
                processes.add(process);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
于 2016-04-13T18:30:34.373 に答える