2

这是一个简单的 Quartz 调度程序,它应该每分钟运行一次作业;作业本身使用 Sonatype Async Http Client发出 HTTP 请求。使用jvisualvm,我能够检测到线程正在产生并且永远不会关闭,例如它们被卡在wait中。这让我相信,要么 A)我误解了 Quartz 如何在这个特定的设置下工作,要么 B)有其他问题。可能是 A :) 调度程序:

public class QuartzAsyncHttpThreadTest {

    /* TEST */
    @SuppressWarnings("rawtypes")
    private static Class jobToRun = AsyncHttpRequestJob.class;
    private static String cron = "0 0/1 * * * ?";
    /* TEST */


    public static void main(String[] args) throws SchedulerException {

        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        scheduler.start();

        start(scheduler, jobToRun.getName(), jobToRun);

    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void start(Scheduler scheduler, String name, Class job)
            throws SchedulerException {

        JobKey monitorKey = new JobKey(name + "_job", "jobs");
        JobDetail detail = JobBuilder.newJob(job).withIdentity(monitorKey)
                .build();

        Trigger cronDef = TriggerBuilder.newTrigger()
                .withIdentity(name + "_trigger", "triggers")
                .withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();

        scheduler.scheduleJob(detail, cronDef);

    }

}

工作:

public class AsyncHttpRequestJob implements Job {

    public AsyncHttpRequestJob() {

    }

    public void execute(JobExecutionContext context)
            throws JobExecutionException {

        System.out.println("Go..");

        makeRequest();

    }

    public static void makeRequest() {

        try {

            Future<Response> r = new AsyncHttpClient().prepareGet(
                    "http://google.com").execute();

            Response response = r.get();

            System.out.println("Request status: " + response.getStatusCode()); // 301

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

}

真的没什么。如果我对活动线程进行分析,则在 2 分钟后,这种侵占就会很明显。首先是 24,然后是 27、30……等等。在此处输入图像描述

编辑

我能够验证它是 AsyncHttpClient 和 Quartz 的组合,就像我makeRequest用标准请求换出方法时一样:

    URL conn = new URL("http://google.com");
    URLConnection httpR = conn.openConnection();
    BufferedReader in = new BufferedReader(new InputStreamReader(
            httpR.getInputStream()));
    String inputLine;

    while ((inputLine = in.readLine()) != null)
        System.out.println(inputLine);
    in.close();

一切都按预期工作。

4

1 回答 1

3

您必须关闭AsyncHttpClient此处创建的每个实例:

Future<Response> r = new AsyncHttpClient().prepareGet(
                "http://google.com").execute();

使用close()方法。每个实例AsyncHttpClient都会创建一些必须清理的资源(如线程)。

但是,由于AsyncHttpClient是线程安全的,更好的方法是只创建一个全局实例,AsyncHttpClient并在应用程序的整个生命周期中以及从多个线程中重用它。

最后,既然您基本上发送一些请求并同步(阻塞)等待响应,为什么不使用标准URLConnection(如您的示例)或HttpClientAsyncHttpClient当您不想同步等待响应时非常有用,例如,当您想同时启动数百个 HTTP 请求而不产生数百个线程时。AsyncHttpClient然后将在响应出现时调用您的回调代码。

于 2012-10-16T17:47:06.680 回答