实习之多线程

来源:互联网 发布:dota2数据分析 编辑:程序博客网 时间:2024/06/05 19:45

最近这段时间都没有更新博客了,自从PowerMock把折磨完以后, 老大给了很多任务,听起来都蛮高大上的实质也就是一些重复的工作。
首先说说我遇到的多线程的问题吧。任务描述:公司有一个服务器监控的开源软件(名字不知道),用图形界面来监控服务器的版本cpu , jvm virtual memory,  jvm total memory. 如果服务器的代码版本发生变化当然在饼图里面他的值就会发生变化。现在我们的Server有许多的state, 其中cpu, jvm memory这些状态都已经完成好他的饼图的实现。我们需要增加一个state就是md5sum, 正常情况下所有的服务器的md5sum值应该是相等的,但是如果在饼图中存在其他的值,那就说明服务器中存在的一些非法的改动。
回归到主题上来,我在实现获取服务器的MD5值得时候采用了多线程的方法,因为公司怎么也得是世界五百强企业,服务器还是蛮多的。如果一个一个服务器是访问那么时间肯定要耗费很多,所以必须使用多线程来解决这个问题。使用到 ExecutorService 


几种不同的ExecutorService线程池对象
1. newCachedThreadPool()   -缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse.如果没有,就建一个新的线程加入池中-缓存型池子通常用于执行一些生存期很短的异步型任务.因此在一些面向连接的daemon型SERVER中用得不多。能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。
  2.newFixedThreadPoolnewFixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待直到当前的线程中某个线程终止直接被移出池子
-和cacheThreadPool不同,FixedThreadPool没有IDLE机制(可能也有,但既然文档没提,肯定非常长,类似依赖上层的TCP或UDP IDLE机制之类的),所以FixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器从方法的源代码看,cache池和fixed 池调用的是同一个底层池,只不过参数不同:fixed池线程数固定,并且是0秒IDLE(无IDLE)cache池线程数支持0-Integer.MAX_VALUE(显然完全没考虑主机的资源承受能力),60秒IDLE 

3. ScheduledThreadPool -调度型线程池。这个池子里的线程可以按schedule依次delay执行,或周期执行

4.SingleThreadExecutor单例线程,任意时间池中只能有一个线程-用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE)

创建任务: 任务就是一个实现了的Runnable接口的类。创建的时候实现run方法即可。

执行任务: 通过java.util.concurrent.ExecutorService接口对象来执行任务,该接口对象通过工具类java.util.concurrent. Excutors的静态方法来创建。Excutors此句中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。ExecutorService提

供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以关闭 ExecutorService,这将导致其停止接受新任务。关闭后,执行程序将最后

终止,这时没有任务在执行,也没有任务在等待执行,并且无法提交新任务。

executorService.execute(new TestRunnable());
        executorService.submit();

2、将任务添加到线程去执行
当将一个任务添加到线程池中的时候,线程池会为每个任务创建一个线程,该线程会在之后的某个时刻自动执行。

关闭执行服务对象: executorService.shutdown();

      获取任务的执行的返回值  在Java5之后,任务分两类:一类是实现了Runnable接口的类,一类是实现了Callable接口的类。两者都可以被 ExecutorService执行,但是

Runnable任务没有返回值,而Callable任务有返回值。并且Callable的call()方法只能通过ExecutorService的(<T> task) 方法来执行,并且返回一个 <T><T>,是表示任务等待

完成的 Future。public interface Callable<V>返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。Callable 接口类似于,两者都是为那些

其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。类包含一些从其他普通形式转换成 Callable 类的实用方法。

Callable中的call()方法类似Runnable的run()方法,就是前者有返回值,后者没有。当将一个Callable的对象传递给ExecutorService的submit方法,则该call方法自动在一个线

程上执行,并且会返回执行结果Future对象。同样,将Runnable的对象传递给ExecutorService的submit方法,则该run方法自动在一个线程上执行,并且会返回执行结果

Future对象,但是在该Future对象上调用get方法,将返回null。                                                                                                                


ExecutorService executorService = Executors.newFixedThreadPool(thread_count);//ExecutorService通常根据系统资源情况灵活定义线程池大小List<Future<ServerStatus>> resultList = new ArrayList<>();try{for(Agent agent : agents){final String host = agent.getLabel().split(":")[1];final String urlStr = String.format("http://%s:8765/aaa/bbb", host);//call api Future<ServerStatus> future = executorService.submit(new Callable<ServerStatus>() {@Overridepublic ServerStatus call() {return buildServerStatus(host, urlStr);}});resultList.add(future);}for (Future<ServerStatus> future : resultList) {try {ServerStatus serverStatus = future.get();MD5Map.put(serverStatus.getHost(), serverStatus);} catch (InterruptedException | ExecutionException e) {logger.error(" Fetech ServerStatus exception: " + e.getMessage());}}


0 0