8月24日

前几天太忙了,鸽了几天

@PostConstruct基本:
@PostConstruct注解好多人以为是Spring提供的。其实是Java自己的注解。

Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:

Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

应用:在静态方法中调用依赖注入的Bean中的方法。

看端口

1
server.port:

countDownLatch

  • countDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。
  • 存在于java.util.cucurrent包下。

概念

  • countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
  • 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

一、ExecutorService介绍

ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法:

Java API对ExecutorService接口的实现有两个,所以这两个即是Java线程池具体实现类(详细了解这两个实现类,点击这里):

  1. ThreadPoolExecutor

  2. ScheduledThreadPoolExecutor

除此之外,ExecutorService还继承了Executor接口(注意区分Executor接口和Executors工厂类),这个接口只有一个execute()方法,最后我们看一下整个继承树:

二、ExecutorService的创建

创建一个什么样的ExecutorService的实例(即线程池)需要g根据具体应用场景而定,不过Java给我们提供了一个Executors工厂类,它可以帮助我们很方便的创建各种类型ExecutorService线程池,Executors一共可以创建下面这四类线程池:

  1. newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  2. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  3. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
  4. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

注意:线程池只是为了控制应用中处理某项业务中防止高并发问题带来的线程不安全的发生的概率。在我目前的测试用,还没有发现线程可以重用这个概念,因为线程开启后,用完就关闭了,不可以再次开启的,查看源码发现会每次新创建一个线程用来处理业务。我们可以通过线程池指定处理这项业务最大的同步线程数,

比如:Executors.newFixedThreadPool(3);在线程池中保持三个线程可以同时执行,但是注意,并不是说线程池中永远都是这三个线程,只是说可以同时存在的线程数,当某个线程执行结束后,会有新的线程进来。newFixedThreadPool.execute(new ThreadForpools());这句话的含义并不是添加新的线程,而是添加新的处理业务请求进来。至少我当前是这么理解的,没有发现线程可以重复使用。

runWorker()通过循环来取任务 通过getTask()方法。这里也就是说worker的run()方法执行了多个任务,从而实现重复使用。多个任务本来是多个线程run()方法执行,这里实现了一个run()执行多个任务。

getTask()方法里用了一个死循环获取任务,如果没有任务时,并且没有受到超时和shutdown命令时,线程将会一直被阻塞在这个方法里。从而实现了线程没有被销毁的目的。

三、ExecutorService的使用

1
2
3
4
5
6
7
ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});

四、ExecutorService的执行

ExecutorService有如下几个执行方法:

  • execute(Runnable)
  • submit(Runnable)
  • submit(Callable)
  • invokeAny(…)
  • invokeAll(…)

4.1 execute(Runnable)

这个方法接收一个Runnable实例,并且异步的执行,请看下面的实例:

1
2
3
4
5
6
7
8
9
10
ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});

executorService.shutdown();

Executors.newSingleThreadExecutor()这种的实现方式,看名字我们就应该知道是使用单线程重来支持的。

jdk的注释说明有介绍 ,它和其他的实现 newFixedThreadPool(1)代码的区别在于,它不支持设置corePoolSize。保证不可使用额外的线程。

FinalizableDelegatedExecutorService重写了finalize方法,并且在该方法中调用了super.shutdown()。它实现了在GC的时候会关闭线程。

主线程就是执行main函数的线程,A线程创建B,那么B就是A的子线程