class ThreadPoolTask implements Runnable, Serializable {
private static final long serialVersionUID = 0; private SendObj jjo; ThreadPoolTask(SendObj jjo) {
this.jjo = jjo;
} public void run() {
try {
this.jjo.SendInfo();
} catch (Exception ex) {
ex.printStackTrace();
}
jjo = null;
}
}public class SendObj {
// corePoolSize: 线程池维护线程的最少数量
// maximumPoolSize:线程池维护线程的最大数量
// keepAliveTime: 线程池维护线程所允许的空闲时间
// unit: 线程池维护线程所允许的空闲时间的单位
// workQueue: 线程池所使用的缓冲队列
// handler: 线程池对拒绝任务的处理策略
// ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
// long keepAliveTime, TimeUnit unit,
// BlockingQueue<Runnable> workQueue,
// RejectedExecutionHandler handler)
// corePoolSize: 线程池维护线程的最少数量
// maximumPoolSize:线程池维护线程的最大数量
// keepAliveTime: 线程池维护线程所允许的空闲时间
// unit: 线程池维护线程所允许的空闲时间的单位
// workQueue: 线程池所使用的缓冲队列
// handler: 线程池对拒绝任务的处理策略 private ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 20, 5,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5),
new ThreadPoolExecutor.CallerRunsPolicy());//

public void SendInfo() {
System.out.println("步骤1:"+System.currentTimeMillis());
 //发信息
} private void runOrder() throws ParseException {
SendObj jjo = new SendObj();
while (true) {
threadPool.execute(new ThreadPoolTask(jjo));
}
} public static void main(String[] args) throws ParseException { long s = System.currentTimeMillis(); new SendObj().runOrder(); long e = System.currentTimeMillis(); System.out.println((Double.parseDouble((e - s) + "") / Double
.parseDouble("1000")) + " 秒");
}
}程序功能:
我这个程序的功能是,不停的发信息,不等执行结果,所以我用上面的线程池实现。我的问题:
我看日志发现,跟我想的不一样,感觉是线程池1拨发完后等这波运行结束了在发一拨。
我希望的是我个毫秒能发尽量多的信息出去,也就是说我希望,我能在最小时间单位尽量快、尽量多的调用某个方法,调用了我就不管了,
我想象的日志是:2013-02-15 19:21:14.319步骤1
2013-02-15 19:21:14.319步骤1:
2013-02-15 19:21:14.319步骤1:
2013-02-15 19:21:14.319步骤1:
2013-02-15 19:21:14.320步骤1
2013-02-15 19:21:14.320步骤1
2013-02-15 19:21:14.320步骤1
.
.
.
因为我觉得这个调用应该跟循环是一样的不应该有什么时间损失,我只管调用我也不管结果。应该不会有时间损失才对吧?希望大家指教啊。看我怎么能够在最短时间内调用尽量多的sendInfo方法,我也不用管这个方法返回情况,我就调用就行了。实际日志如下:
2013-02-15 19:21:14.319步骤1
2013-02-15 19:21:14.319步骤1:
2013-02-15 19:21:14.319步骤1:
2013-02-15 19:21:14.319步骤1:
2013-02-15 19:21:15.336步骤1
2013-02-15 19:21:15.352@
2013-02-15 19:21:15.352@
.
.
.
.

解决方案 »

  1.   

    线程的调度受限于操作系统,本身就无法决定到底先调用那个线程,你希望的是先调用主线程,但实际运行中并不一定;另外你创建的线程池最大为20个线程,所以启动20个线程后只能等待前面的执行完了, 有空闲线程了才能继续添加线程。根据你的要求可以通过以下几种方法改进:首先,可以在子线程中加入sleep语句,使主线程获得更多的时间片;其次可以调高线程池的大小,使同时运行的线程更多。剩下的就要依赖你的操作系统的调度算法和你的cpu的运算速度了。
      

  2.   

    普通级别的线程,执行顺序不确定的,想达到你那种效果,用Thread.sleep()控制吧。
      

  3.   

    你这样写没有造成时间损失啊。  你要想到JAVA本来就不能独占CPU吧 你还开了很多别的程序呢。 public class TestClass {
    public static void main(String[] args) throws Exception {
    while(1==1){
    System.out.println(System.currentTimeMillis());
    }
    }
    }这样够连贯了吧。 仍然不是每一毫秒接着的
      

  4.   


    楼主你的期望是无法实现的,这关系到操作系统调度的问题。实际上,任何时间函数都是用操作系统时间片计时,多核下Windows的时间片是15毫秒,单核10毫秒,决定了你的最高精度10-15毫秒。所以楼主你的理想怕是要落空了。
      

  5.   

    我可能没有描述清楚,由于我的SendInfo()是向一个网页发请求,所以我想有没有那种异步的概念啊,就是我发一个post请求是异步的概念,就是我发出去就不用我管了,我再继续发下一个啊
      

  6.   

    我可能没有描述清楚,由于我的SendInfo()是向一个网页发请求,所以我想有没有那种异步的概念啊,就是我发一个post请求是异步的概念,就是我发出去就不用我管了,我再继续发下一个啊,不用等待post请求的返回。
      

  7.   


    我发送请求方法如下:
    StringBuffer strBuffer = new StringBuffer(httpClient.execute(httpost,responseHandler));日志返回如下:下面日志显示同一个请求,耗时差别很大,我想可能是当时系统负载过大造成的,是不是由于我写
    StringBuffer strBuffer = new StringBuffer(httpClient.execute(httpost,responseHandler));
    所以比较慢,如果写httpClient.execute(httpost,responseHandler)是不是就会快点,
    因为不用等返回结果,只是把指令发送出去就行了?2013-02-15 08:00:22.167@ 请求URL:http://10.11.5.91:80/action/InfoAction 返回结果:{"message":"201302FY048656","object":[ok],"success":true} 
    2013-02-15 08:00:22.167@ 执行耗时:702 毫秒
    2013-02-15 08:00:22.448@ 请求URL:http://10.11.5.91:80/action/InfoAction 返回结果:{"message":"201302FY048657","object":[ok],"success":true} 
    2013-02-15 08:00:22.448@ 执行耗时:952 毫秒
    2013-02-15 08:00:23.962@ 请求URL:http://10.11.5.91:80/action/InfoAction 返回结果:{"message":"201302FY048663","object":[ok],"success":true} 
    2013-02-15 08:00:23.962@ 执行耗时:2466 毫秒
    2013-02-15 08:00:25.367@ 请求URL:http://10.11.5.91:80/action/InfoAction 返回结果:{"message":"201302FY048667","object":[ok],"success":true} 2013-02-15 08:00:25.367@ 执行耗时:3871 毫秒
    2013-02-15 08:00:25.399@ 请求URL:http://10.11.5.91:80/action/InfoAction 返回结果:{"message":"success":false} 
    2013-02-15 08:00:25.399@ 执行耗时:3903 毫秒
    2013-02-15 08:00:25.586@ 请求URL:http://10.11.5.91:80/action/InfoAction 返回结果:{"message":"success":false} 
    2013-02-15 08:00:25.586@ 执行耗时:4090 毫秒2013-02-15 19:35:00.948@ 请求URL:http://10.11.5.91:80/action/InfoAction 返回结果:{"message":"success":false} 
    2013-02-15 19:35:00.988@ 执行耗时:210 毫秒
    2013-02-15 19:35:00.988@ 请求URL:请求URL:http://10.11.5.91:80/action/InfoAction 返回结果:{"message":"success":false}
    2013-02-15 19:35:01.138@ 执行耗时:190 毫秒
      

  8.   


    先说下一个问题:HttpClient 是非并发安全的,也就是只能单线程使用,或者你要每个线程创建一个对象。
    其次是:HttpClient是同步请求,也就是阻塞式的。如果你喜欢彻底的异步,请使用 HttpAsyncClient
    “同一个请求,耗时差别很大”这个未必不正常,也许是网络、带宽等其它原因引起的;要排除此类问题,最好先尝试本机测试,也即请求:http://localhost:80/action/InfoAction 
      

  9.   

    我又想了想啊,我的HttpClient 只有一个啊,我只是用这个HttpClient 不停地post 而已啊
      

  10.   


    我看你这段代码是这样的:
    private void runOrder() throws ParseException {
          SendObj jjo = new SendObj(); // 这个对象应该持有HttpClient是吧?
          while (true) {
                threadPool.execute(new ThreadPoolTask(jjo)); //你不停的创建任务给线程池
          }
    }
    那么线程池是多线程的,也就意味着多个线程同时使用jjo,应该是存在隐患的。当然不清楚你的SendObj啥样,也许你做了同步控制啥的。
      

  11.   

    是通过一个HttpClient对象不停post,但因为是阻塞式执行(内部可能是同步了的,不是很清楚,可以通过观察执行效果得知),所以即使通过多线程方式执行同一个HttpClient对象的post,整体效果上也很可能是顺序执行,不知道是不是这样?这里有一个小例子,也许有用?from: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fluent.html#d5e1274
    ExecutorService threadpool = Executors.newFixedThreadPool(2);
    Async async = Async.newInstance().use(threadpool);Request[] requests = new Request[] {
            Request.Get("http://www.google.com/"),
            Request.Get("http://www.yahoo.com/"),
            Request.Get("http://www.apache.com/"),
            Request.Get("http://www.apple.com/")
    };Queue<Future<Content>> queue = new LinkedList<Future<Content>>();
    for (final Request request: requests) {
        Future<Content> future = async.execute(request, new FutureCallback<Content>() {
            
            public void failed(final Exception ex) {
                System.out.println(ex.getMessage() + ": " + request);
            }
            
            public void completed(final Content content) {
                System.out.println("Request completed: " + request);
            }
            
            public void cancelled() {
            }
            
        });
        queue.add(future);
    }// Process the queue
      

  12.   


    或者你加个群吧:229609257,Ticmy的并发讨论群;我也在群里。
      

  13.   


    没有做同步啊~但是应该没有问题吧。我的思路就是用httpclient建立一个连接通道啊,然后在这个通道上,尽量多的发一个post请求,就好比我登陆csdn以后这一个用户不停的发不同的帖子一样啊
      

  14.   


    您一说我就看了HttpAsyncClient啊~但是例子和说明好少啊,我现在思路是我用httpclient建立链接然后怎么能用HttpAsyncClient去send post请求。希望您可以指导一下啊。谢谢了
      

  15.   

    我也没用过HttpAsyncClient,遇到什么问题直接发出来好了,大家一起讨论或怎么样,或者问ldh911大侠。
      

  16.   

    httpclient是阻塞式的,建立再多的通道也是一样,也只能等这一个应答结束后再进行下一个。你想“尽量多的发一个post请求”不知道想要的结果是什么。况且响应的时间是不确定的,与好多因素有关。
      

  17.   

    需求比较不好描述啊,但是就好比一个用户登录了csdn他可以开多个sheet然后同时发不同的帖子,我也是用
    同一个httpclient采用threadpool并非调用这个ttpclient的post方法而已啊。
      

  18.   

    所以听你们说我打算异步的post只发post啊~不理会结果。
      

  19.   


    大侠啊~你说我该怎么实现啊。
    我看了HttpAsyncClient啊~但是例子和说明好少啊,我现在思路是我用httpclient建立链接,然后怎么能用HttpAsyncClient去异步send post请求啊。希望您可以指导一下啊。谢谢了 
      

  20.   

    这里有些例子都看过了吗?http://hc.apache.org/httpcomponents-asyncclient-dev/examples.html比如这个:package org.apache.http.examples.nio.client;import java.util.concurrent.CountDownLatch;import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.concurrent.FutureCallback;
    import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
    import org.apache.http.nio.client.HttpAsyncClient;
    import org.apache.http.params.CoreConnectionPNames;public class AsyncClientHttpExchangeFutureCallback {    public static void main(String[] args) throws Exception {
            HttpAsyncClient httpclient = new DefaultHttpAsyncClient();
            httpclient.getParams()
                .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 3000)
                .setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 3000)
                .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
                .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);        httpclient.start();
            try {
                HttpGet[] requests = new HttpGet[] {
                        new HttpGet("http://www.apache.org/"),
                        new HttpGet("https://www.verisign.com/"),
                        new HttpGet("http://www.google.com/")
                };
                final CountDownLatch latch = new CountDownLatch(requests.length);
                for (final HttpGet request: requests) {
                    httpclient.execute(request, new FutureCallback<HttpResponse>() {                    public void completed(final HttpResponse response) {
                            latch.countDown();
                            System.out.println(request.getRequestLine() + "->" + response.getStatusLine());
                        }                    public void failed(final Exception ex) {
                            latch.countDown();
                            System.out.println(request.getRequestLine() + "->" + ex);
                        }                    public void cancelled() {
                            latch.countDown();
                            System.out.println(request.getRequestLine() + " cancelled");
                        }                });
                }
                latch.await();
                System.out.println("Shutting down");
            } finally {
                httpclient.shutdown();
            }
            System.out.println("Done");
        }}它是构建了一个HttpGet的数组,你是要post,类似的,换成post试试吧,不知道你试过没有