Java5对线程处理的新操作-concurrent包介绍

上节中简单介绍了传统的jdk中的线程的概念,本节中接着介绍下jdk5之后对线程处理有哪些改变。

 

首先,介绍下java.util.concurrent包下有个字包atomic(原子的)包,其中的一些类提供原子性操作类,分别是:

1 AtomicBoolean,
2 AtomicInteger,AtomicIntegerArray,AtomicIntegerFieldUpdater<T>3 AtomicLong,AtomicLongArray,AtomicLongFieldUpdater<T>4 AtomicReference<V>,AtomicReferenceArray<E>,AtomicReferenceFieldUpdater<T,V>5 AtomicMarkableReference<V>6 AtomicStampedReference<V>

atomic包可以对基本数据,数组中的基本数据,对类中的基本数据进行原子性操作。

 

在介绍了在多线程环境下jdk提供了原子操作类的基本实现后,我们接着介绍线程并发库的应用。

  线程池的概念,线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。

  实例,Tomcat服务器设计思路。
技术分享

线程池实现:在线程run实现中,while(查询某个线程池中是否有任务==有){执行任务}

  jdk中默认提供了,Executes类供开发者使用,该类中提供静态方法用于创建不同类型的线程池。

在线程池学习中大家,只需注意两点,线程池中线程的数量,和我们向线程池中丢了多少任务。

我们不需要自己去把任务交给线程运行,而只需将任务丢到线程池中,由线程池自动帮我们运行,当线程池中没有空闲线程时候我们可以采用多种机制处理线程。处理方式如下:

1. 创建固定数量的连接池。

 1 ExecutorService pool = Executors.newFixedThreadPool(3);
 2 for (int i = 0; i < 10; i++) {
 3     final int task  = i;
 4     pool.execute(new Runnable() {
 5         @Override
 6         public void run() {
 7             for (int i = 0; i < 10; i++) {
 8         try {
 9                 Thread.sleep(20);
10         } catch (InterruptedException e) {
11             }
12                 System.out.println(Thread.currentThread().getName()+": is looping of "+i+" for task is "+task);
13         }
14         }
15     });
16 }    

线程的执行执行结果:

 1 pool-1-thread-3: is looping of 0 for task is 2
 2 pool-1-thread-1: is looping of 0 for task is 0
 3 pool-1-thread-2: is looping of 0 for task is 1
 4 pool-1-thread-2: is looping of 1 for task is 1
 5 pool-1-thread-1: is looping of 1 for task is 0
 6 pool-1-thread-3: is looping of 1 for task is 2
 7 pool-1-thread-2: is looping of 2 for task is 1
 8 pool-1-thread-1: is looping of 2 for task is 0
 9 pool-1-thread-3: is looping of 2 for task is 2
10 pool-1-thread-2: is looping of 3 for task is 1
11 pool-1-thread-3: is looping of 3 for task is 2
12 pool-1-thread-1: is looping of 3 for task is 0

从结果可以看出,我们创建了一个固定三个长度的线程池对象,并且向线程池中丢了10个任务Task,在执行的过程中这些任务会同时被3个线程同时执行,在3个线程执行的过程中,第4个任务并不会执行,而被挂起排队中,因为此时我们创建的是固定数量的线程池,直到3个线程中有一个线程结束时候才会执行第4个任务。
这个就是固定数量的线程池-Fixed线程池,在所有任务都执行完成后,主任务并不死亡,因为线程池中的线程并不死亡,如果要主程序死亡,需要执行shutdown()或者shutdownNow()方法。

2. 创建缓存的线程池

 1 ExecutorService pool = Executors.newCachedThreadPool();
 2 for (int i = 0; i < 10; i++) {
 3     final int task  = i;
 4     pool.execute(new Runnable() {
 5        @Override
 6     public void run() {
 7         for (int i = 0; i < 10; i++) {
 8         try {
 9             Thread.sleep(20);
10         } catch (InterruptedException e) {}
11                     System.out.println(Thread.currentThread().getName()+": is looping of "+i+" for task is "+task);
12         }
13         }
14     });
15 }

执行结果如下:

pool-1-thread-1: is looping of 0 for task is 0
pool-1-thread-3: is looping of 0 for task is 2
pool-1-thread-5: is looping of 0 for task is 4
pool-1-thread-7: is looping of 0 for task is 6
pool-1-thread-2: is looping of 0 for task is 1
pool-1-thread-4: is looping of 0 for task is 3
pool-1-thread-6: is looping of 0 for task is 5
pool-1-thread-8: is looping of 0 for task is 7
pool-1-thread-10: is looping of 0 for task is 9
pool-1-thread-9: is looping of 0 for task is 8
pool-1-thread-1: is looping of 1 for task is 0

程序会自动创建相应数量的线程来处理相应数量的任务,这就是带缓存的线程池。

当线程服务不过来时候时候它自动增加新的线程。线程池中线程数量是不固定的,

当线程服务任务数量变化时候,超时一段时间后我们会将线程收回,不浪费。

3. 创建单个线程的线程池,类似单线程。

 1  ExecutorService pool = Executors.newSingleThreadExecutor();
 2  for (int i = 0; i < 10; i++) {
 3     final int task = i;
 4      pool.execute(new Runnable() {
 5         @Override
 6         public void run() {
 7           for (int i = 0; i < 10; i++) {
 8              try {
 9                  Thread.sleep(500);
10               } catch (InterruptedException e) {}
11                  System.out.println(Thread.currentThread().getName()+ ": is looping of " + i + " for task is "+ task);
12          }
13         }
14      });
15  }
16     

执行结果:

pool-1-thread-1: is looping of 0 for task is 0
pool-1-thread-1: is looping of 1 for task is 0
pool-1-thread-1: is looping of 2 for task is 0
pool-1-thread-1: is looping of 3 for task is 0
pool-1-thread-1: is looping of 4 for task is 0
pool-1-thread-1: is looping of 5 for task is 0
pool-1-thread-1: is looping of 6 for task is 0
pool-1-thread-1: is looping of 7 for task is 0
pool-1-thread-1: is looping of 8 for task is 0
pool-1-thread-1: is looping of 9 for task is 0
pool-1-thread-1: is looping of 0 for task is 1
pool-1-thread-1: is looping of 1 for task is 1
pool-1-thread-1: is looping of 2 for task is 1
pool-1-thread-1: is looping of 3 for task is 1
pool-1-thread-1: is looping of 4 for task is 1

根据结果可以看出,在创建单个线程时候,任务是按照放入的顺序单独执行的,即当第一个任务执行完成后会在创建一个线程(还是原来的名字)处理下一个任务,保证存在一个线程,解决线程死亡后重新启动。

4. 定时器线程池,用线程池启动定时器。

ScheduledExecutorService executorService=Executors.newScheduledThreadPool(3);
executorService.scheduleAtFixedRate(new Runnable() {
    public void run() {
    System.out.println("execute1");
    }
}, 2 ,1 , TimeUnit.SECONDS);
executorService.schedule(new Runnable() {
    public void run() {
    System.out.println("execute2");
    }
}, 2 ,TimeUnit.SECONDS);

对于定时器的线程池操作,

  schedule,多久开始执行一次;

  scheduleAtFixedRate,多就开始执行一次后,再隔多少秒再执行一次,且不受任务执行时间影响;

  scheduleWithFixedDelay,多就开始执行一次后,再隔多少秒再执行一次,且受任务执行时间影响;

 

 



 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。