Java 线程通过AsyncHttpClient和Quartz作业疯狂运行

Java 线程通过AsyncHttpClient和Quartz作业疯狂运行,java,multithreading,http,quartz-scheduler,jvisualvm,Java,Multithreading,Http,Quartz Scheduler,Jvisualvm,下面是一个简单的Quartz调度程序,它应该每分钟运行一次作业;作业本身使用Sonatype发出HTTP请求。使用jvisualvm,我能够检测到线程的繁殖和从不关闭,例如,它们被困在等待中。这让我相信,要么A)我误解了石英如何与这个特定的设置一起工作,要么B)其他的东西出了问题。可能是:)调度程序: public class QuartzAsyncHttpThreadTest { /* TEST */ @SuppressWarnings("rawtypes") pri

下面是一个简单的Quartz调度程序,它应该每分钟运行一次作业;作业本身使用Sonatype发出HTTP请求。使用
jvisualvm
,我能够检测到线程的繁殖和从不关闭,例如,它们被困在等待中。这让我相信,要么A)我误解了石英如何与这个特定的设置一起工作,要么B)其他的东西出了问题。可能是:)调度程序:

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();
        }
    }

}

所有工作正常。

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

Future<Response> r = new AsyncHttpClient().prepareGet(
                "http://google.com").execute();
Future r=new AsyncHttpClient().prepareGet(
"http://google.comexecute();
使用方法。
AsyncHttpClient
的每个实例都会创建一些必须清理的资源(如线程)

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


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

您是否可以对卡住的线程进行线程转储(例如,使用
jvisualvm
)?它们是否挂在
r.get()
上?是否显示过请求状态:?如果你仍然同步地等待响应,为什么还要使用异步客户端呢?从文档上看,它说这是使用异步客户端的阻塞方式,不是吗?所以我觉得这不重要。我确实看到“请求状态”被记录。我可以转储线程,但每次都会出现图中所示的AsyncHttpClient Reaper线程。
Future<Response> r = new AsyncHttpClient().prepareGet(
                "http://google.com").execute();