多线程调用问题啊线程池

Kyle-soft 2013-02-16 06:57:07
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@
.
.
.
.
...全文
421 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
dracularking 2013-02-19
  • 打赏
  • 举报
回复
这里有些例子都看过了吗? 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试试吧,不知道你试过没有
Kyle-soft 2013-02-19
  • 打赏
  • 举报
回复
引用 15 楼 ldh911 的回复:
引用 11 楼 zlyperson 的回复:5555感谢啊~但是听得不是很明白啊,能不能加个q啊,我的q是2605277035~~再次感谢 或者你加个群吧:229609257,Ticmy的并发讨论群;我也在群里。
大侠啊~你说我该怎么实现啊。 我看了HttpAsyncClient啊~但是例子和说明好少啊,我现在思路是我用httpclient建立链接,然后怎么能用HttpAsyncClient去异步send post请求啊。希望您可以指导一下啊。谢谢了
Kyle-soft 2013-02-19
  • 打赏
  • 举报
回复
引用 19 楼 dracularking 的回复:
引用 16 楼 zlyperson 的回复:引用 10 楼 dracularking 的回复:看它每步有的耗时都能达到4090 毫秒之多,看以看出是阻塞式的 问题有些返回就很快,所以我想是不是压力过大的时候服务器反应就慢了。? 是这样,如果不阻塞,就应该立即返回,只是执行一个方法调用而已(只要得到执行就会立即返回,明显不会消耗4秒多这样),方法最耗时的处理过程不会……
所以听你们说我打算异步的post只发post啊~不理会结果。
Kyle-soft 2013-02-19
  • 打赏
  • 举报
回复
引用 21 楼 fangmingshijie 的回复:
httpclient是阻塞式的,建立再多的通道也是一样,也只能等这一个应答结束后再进行下一个。你想“尽量多的发一个post请求”不知道想要的结果是什么。况且响应的时间是不确定的,与好多因素有关。
需求比较不好描述啊,但是就好比一个用户登录了csdn他可以开多个sheet然后同时发不同的帖子,我也是用 同一个httpclient采用threadpool并非调用这个ttpclient的post方法而已啊。
Kyle-soft 2013-02-19
  • 打赏
  • 举报
回复
引用 14 楼 dracularking 的回复:
引用 12 楼 zlyperson 的回复:我又想了想啊,我的HttpClient 只有一个啊,我只是用这个HttpClient 不停地post 而已啊 是通过一个HttpClient对象不停post,但因为是阻塞式执行(内部可能是同步了的,不是很清楚,可以通过观察执行效果得知),所以即使通过多线程方式执行同一个HttpClient对象的post,整体效果上也很可能是……
您一说我就看了HttpAsyncClient啊~但是例子和说明好少啊,我现在思路是我用httpclient建立链接然后怎么能用HttpAsyncClient去send post请求。希望您可以指导一下啊。谢谢了
Kyle-soft 2013-02-19
  • 打赏
  • 举报
回复
引用 13 楼 ldh911 的回复:
引用 12 楼 zlyperson 的回复:我又想了想啊,我的HttpClient 只有一个啊,我只是用这个HttpClient 不停地post 而已啊 我看你这段代码是这样的: private void runOrder() throws ParseException { SendObj jjo = new SendObj(); // 这个对象应该……
没有做同步啊~但是应该没有问题吧。我的思路就是用httpclient建立一个连接通道啊,然后在这个通道上,尽量多的发一个post请求,就好比我登陆csdn以后这一个用户不停的发不同的帖子一样啊
Kyle-soft 2013-02-19
  • 打赏
  • 举报
回复
引用 10 楼 dracularking 的回复:
看它每步有的耗时都能达到4090 毫秒之多,看以看出是阻塞式的
问题有些返回就很快,所以我想是不是压力过大的时候服务器反应就慢了。?
  • 打赏
  • 举报
回复
httpclient是阻塞式的,建立再多的通道也是一样,也只能等这一个应答结束后再进行下一个。你想“尽量多的发一个post请求”不知道想要的结果是什么。况且响应的时间是不确定的,与好多因素有关。
dracularking 2013-02-19
  • 打赏
  • 举报
回复
引用 18 楼 zlyperson 的回复:
引用 14 楼 dracularking 的回复:引用 12 楼 zlyperson 的回复:我又想了想啊,我的HttpClient 只有一个啊,我只是用这个HttpClient 不停地post 而已啊 是通过一个HttpClient对象不停post,但因为是阻塞式执行(内部可能是同步了的,不是很清楚,可以通过观察执行效果得知),所以即使通过多线程方式执行同一个Htt……
我也没用过HttpAsyncClient,遇到什么问题直接发出来好了,大家一起讨论或怎么样,或者问ldh911大侠。
dracularking 2013-02-19
  • 打赏
  • 举报
回复
引用 16 楼 zlyperson 的回复:
引用 10 楼 dracularking 的回复:看它每步有的耗时都能达到4090 毫秒之多,看以看出是阻塞式的 问题有些返回就很快,所以我想是不是压力过大的时候服务器反应就慢了。?
是这样,如果不阻塞,就应该立即返回,只是执行一个方法调用而已(只要得到执行就会立即返回,明显不会消耗4秒多这样),方法最耗时的处理过程不会阻碍方法的返回。
MiceRice 2013-02-17
  • 打赏
  • 举报
回复
引用 11 楼 zlyperson 的回复:
5555感谢啊~但是听得不是很明白啊,能不能加个q啊,我的q是2605277035~~再次感谢
或者你加个群吧:229609257,Ticmy的并发讨论群;我也在群里。
dracularking 2013-02-17
  • 打赏
  • 举报
回复
引用 12 楼 zlyperson 的回复:
我又想了想啊,我的HttpClient 只有一个啊,我只是用这个HttpClient 不停地post 而已啊
是通过一个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
MiceRice 2013-02-17
  • 打赏
  • 举报
回复
引用 12 楼 zlyperson 的回复:
我又想了想啊,我的HttpClient 只有一个啊,我只是用这个HttpClient 不停地post 而已啊
我看你这段代码是这样的: private void runOrder() throws ParseException { SendObj jjo = new SendObj(); // 这个对象应该持有HttpClient是吧? while (true) { threadPool.execute(new ThreadPoolTask(jjo)); //你不停的创建任务给线程池 } } 那么线程池是多线程的,也就意味着多个线程同时使用jjo,应该是存在隐患的。 当然不清楚你的SendObj啥样,也许你做了同步控制啥的。
Kyle-soft 2013-02-17
  • 打赏
  • 举报
回复
引用 9 楼 ldh911 的回复:
引用 8 楼 zlyperson 的回复:我发送请求方法如下: 先说下一个问题:HttpClient 是非并发安全的,也就是只能单线程使用,或者你要每个线程创建一个对象。 其次是:HttpClient是同步请求,也就是阻塞式的。如果你喜欢彻底的异步,请使用 HttpAsyncClient “同一个请求,耗时差别很大”这个未必不正常,也许是网络、带……
我又想了想啊,我的HttpClient 只有一个啊,我只是用这个HttpClient 不停地post 而已啊
Kyle-soft 2013-02-17
  • 打赏
  • 举报
回复
引用 9 楼 ldh911 的回复:
引用 8 楼 zlyperson 的回复:我发送请求方法如下: 先说下一个问题:HttpClient 是非并发安全的,也就是只能单线程使用,或者你要每个线程创建一个对象。 其次是:HttpClient是同步请求,也就是阻塞式的。如果你喜欢彻底的异步,请使用 HttpAsyncClient “同一个请求,耗时差别很大”这个未必不正常,也许是网络、带……
5555感谢啊~但是听得不是很明白啊,能不能加个q啊,我的q是2605277035~~再次感谢
dracularking 2013-02-16
  • 打赏
  • 举报
回复
看它每步有的耗时都能达到4090 毫秒之多,看以看出是阻塞式的
熊猫大虾 2013-02-16
  • 打赏
  • 举报
回复
引用 3 楼 a12939026 的回复:
你这样写没有造成时间损失啊。 你要想到JAVA本来就不能独占CPU吧 你还开了很多别的程序呢。 Java code?1234567public class TestClass { public static void main(String[] args) throws Exception { while(1==1){ Sy……
这个说的好
a12939026 2013-02-16
  • 打赏
  • 举报
回复
你这样写没有造成时间损失啊。 你要想到JAVA本来就不能独占CPU吧 你还开了很多别的程序呢。

public class TestClass {
	public static void main(String[] args) throws Exception {
		while(1==1){
			System.out.println(System.currentTimeMillis());
		}
	}
}
这样够连贯了吧。 仍然不是每一毫秒接着的
MiceRice 2013-02-16
  • 打赏
  • 举报
回复
引用 8 楼 zlyperson 的回复:
我发送请求方法如下:
先说下一个问题:HttpClient 是非并发安全的,也就是只能单线程使用,或者你要每个线程创建一个对象。 其次是:HttpClient是同步请求,也就是阻塞式的。如果你喜欢彻底的异步,请使用 HttpAsyncClient “同一个请求,耗时差别很大”这个未必不正常,也许是网络、带宽等其它原因引起的;要排除此类问题,最好先尝试本机测试,也即请求:http://localhost:80/action/InfoAction
  • 打赏
  • 举报
回复
普通级别的线程,执行顺序不确定的,想达到你那种效果,用Thread.sleep()控制吧。
加载更多回复(5)

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧