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@
.
.
.
.
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@
.
.
.
.
public static void main(String[] args) throws Exception {
while(1==1){
System.out.println(System.currentTimeMillis());
}
}
}这样够连贯了吧。 仍然不是每一毫秒接着的
楼主你的期望是无法实现的,这关系到操作系统调度的问题。实际上,任何时间函数都是用操作系统时间片计时,多核下Windows的时间片是15毫秒,单核10毫秒,决定了你的最高精度10-15毫秒。所以楼主你的理想怕是要落空了。
我发送请求方法如下:
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 毫秒
先说下一个问题:HttpClient 是非并发安全的,也就是只能单线程使用,或者你要每个线程创建一个对象。
其次是:HttpClient是同步请求,也就是阻塞式的。如果你喜欢彻底的异步,请使用 HttpAsyncClient
“同一个请求,耗时差别很大”这个未必不正常,也许是网络、带宽等其它原因引起的;要排除此类问题,最好先尝试本机测试,也即请求:http://localhost:80/action/InfoAction
我看你这段代码是这样的:
private void runOrder() throws ParseException {
SendObj jjo = new SendObj(); // 这个对象应该持有HttpClient是吧?
while (true) {
threadPool.execute(new ThreadPoolTask(jjo)); //你不停的创建任务给线程池
}
}
那么线程池是多线程的,也就意味着多个线程同时使用jjo,应该是存在隐患的。当然不清楚你的SendObj啥样,也许你做了同步控制啥的。
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
或者你加个群吧:229609257,Ticmy的并发讨论群;我也在群里。
没有做同步啊~但是应该没有问题吧。我的思路就是用httpclient建立一个连接通道啊,然后在这个通道上,尽量多的发一个post请求,就好比我登陆csdn以后这一个用户不停的发不同的帖子一样啊
您一说我就看了HttpAsyncClient啊~但是例子和说明好少啊,我现在思路是我用httpclient建立链接然后怎么能用HttpAsyncClient去send post请求。希望您可以指导一下啊。谢谢了
同一个httpclient采用threadpool并非调用这个ttpclient的post方法而已啊。
大侠啊~你说我该怎么实现啊。
我看了HttpAsyncClient啊~但是例子和说明好少啊,我现在思路是我用httpclient建立链接,然后怎么能用HttpAsyncClient去异步send post请求啊。希望您可以指导一下啊。谢谢了
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试试吧,不知道你试过没有