java多线程入门到理解学习笔记

来源:互联网 发布:网络爬虫怎么用 编辑:程序博客网 时间:2024/06/05 06:49

本文记录了我个人在学习java多线程的时候,从入门到理解的学习过程,供同类小白进行学习参考。首先对现有的多线程实现方式进行总结,然后针对最佳多线程实现方式:线程池的要点进行记录,最后记录了在spring框架中线程池的实现方式。

多线程的实现方式

根据多线程的从简到繁的实现方式,可分为三种:继承Thread类、实现Runnable接口、使用进程池。但其中Thread类也是一个实现了Runnable接口的类,而线程池的实现也只是对实现了Runnable类的管理。

初识多线程参考:http://www.cnblogs.com/yezhenhan/archive/2012/01/09/2317636.html

继承Thread类

简单方便,适用于简单、独立的应用,无法继承现有类,不能获取线程返回值,更不能对现有线程进行管理;

实现Runnable接口

简单方便,可继承现有类,不能获取线程返回值,不能对现有线程进行管理;

进程池

即使用Executor框架,Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。
经典关系图:
这里写图片描述

使用线程池的好处:

  • 减少在创建和销毁线程上所花的时间以及系统资源的开销
  • 如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”。

参考链接:

  • 初识Executor框架:http://blog.csdn.net/salonzhou/article/details/50790872
  • 深入Executor框架:http://blog.csdn.net/ns_code/article/details/17465497

线程池详解

此部分对线程池的元素进行进一步理解。包括:Executor,Executors,ExecutorService,CompletionService,Future,Callable,自定义线程池。

Executor

Executor接口中之定义了一个方法execute(Runnable command),该方法接收一个Runable实例,它用来执行一个任务,任务即一个实现了Runnable接口的类。

ExecutorService

ExecutorService接口继承自Executor接口,它提供了更丰富的实现多线程的方法,比如,ExecutorService提供了关闭自己的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以调用ExecutorService的shutdown()方法来平滑地关闭 ExecutorService,调用该方法后,将导致ExecutorService停止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另一类是还没有开始执行的),当所有已经提交的任务执行完毕后将会关闭ExecutorService。因此我们一般用该接口来实现和管理多线程。

ExecutorService接口提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

Executors

Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
方法包括:

  • public static ExecutorService newFixedThreadPool(int nThreads) 创建固定数目线程的线程池。应用场景:只有当这种方式会引发问题时(比如需要大量长时间面向连接的线程时),才需要考虑用FixedThreadPool。
  • public static ExecutorService newCachedThreadPool() 与newFixedThreadPool功能基本相同,不同之处在于不能限定最大线程数且自身能够指定超时时间。创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
  • public static ExecutorService newSingleThreadExecutor() 应用场景:创建一个单线程化的Executor。能添加多个线程,但是不能并行,没有超时时间。
  • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
    应用场景:创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

一般来说,CachedTheadPool在程序执行过程中通常会创建与所需数量相同的线程,然后在它回收旧线程时停止创建新线程,因此它是合理的Executor的首选,只有当这种方式会引发问题时(比如需要大量长时间面向连接的线程时),才需要考虑用FixedThreadPool。(该段话摘自《Thinking in Java》第四版)

CompletionService

任意任务完成后就把其结果加到result中,而不用依次等待每个任务完成,可以使用CompletionService。

Future

获取线程的返回结果,如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

Callable

必须实现Callable接口才能获取到返回结果。Runnable任务没有返回值,而Callable任务有返回值。并且Callable的call()方法只能通过ExecutorService的submit(Callable task) 方法来执行,并且返回一个 Future,是表示任务等待完成的 Future。实现Runnable的接口也能调用get方法,但是结果始终为null。

自定义线程池

可以用ThreadPoolExecutor类创建。

spring的线程池

spring提供了org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor类,通过在xml文件中配置,然后注入到需要用到线程池的对象实例中,即可使用。
简单配置参考如下:

<bean id="taskExecutor"  class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">      <property name="corePoolSize" value="5" />      <property name="maxPoolSize" value="10" />      <property name="WaitForTasksToCompleteOnShutdown" value="true" />      <!--还有其他可配参数--></bean> 

入门参考:http://blog.csdn.net/chszs/article/details/8219189/

==================================
==疑问?帮助?批评?欢迎评论 | QQ:593159978==
==================================

原创粉丝点击