JAVA线程池Executor的简单使用

         在JDK1.5之前,如果需要使用线程池,需要自己动手写代码实现,这对于初学者来说,不是一件容易的事。JDK1.5提供了Executor类,用户通过它可得到各种类型的线程池。

 

         Executor提供的线程池,可以分为:固定尺寸的线程池、可变尺寸的线程池。

 

 Executor.java提供部分接口

public static ExecutorService newFixedThreadPool(int nThreads)创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
public static ExecutorService newSingleThreadExecutor()创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。
public static ExecutorService newCachedThreadPool()创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
public static ScheduledExecutorService newSingleThreadScheduledExecutor()创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。

 

       public static ExecutorService newFixedThreadPool(int n),线程池中有n个线程,如果实际线程数m,m>n,则先加入的前n个线程,先执行,处于执行状态,后加入的m-n个线程,处于阻塞状态,直到有某个线程执行完了,则处于阻塞状态的线程中的其中一个启动。也就是说最多同时n个线程处于执行状态。

package thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolTest {
	public static void main(String[] args) {
		ExecutorService executorService=Executors.newFixedThreadPool(3);
		MyThread a=new MyThread("A");
		MyThread b=new MyThread("B");
		MyThread c=new MyThread("C");
		MyThread d=new MyThread("D");
		
		
		executorService.execute(a);
		executorService.execute(b);
		executorService.execute(c);
		executorService.execute(d);
		
		
		executorService.shutdown();
	}
	
	static class MyThread implements Runnable{
		private String name;
		public MyThread(String name){
			this.name=name;
		}
		@Override
		public void run(){
			for(int i=1;i<=5;i++){
				System.out.println(this.name+"第"+i+"次运行.........");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

运行结果


B第1次运行.........
C第1次运行.........
A第1次运行.........
B第2次运行.........
C第2次运行.........
A第2次运行.........
B第3次运行.........
C第3次运行.........
A第3次运行.........
B第4次运行.........
C第4次运行.........
A第4次运行.........
B第5次运行.........
C第5次运行.........
A第5次运行.........
D第1次运行.........
D第2次运行.........
D第3次运行.........
D第4次运行.........
D第5次运行.........

        ABC同时启动,所以打印顺序是混乱的;最后有空闲线程资源执行D时,只有它在执行,所以看上去有序。

 

       public static ExecutorService newSingleThreadExecutor()线程池中的线程数为1,如果实际线程数大于1时,则按照加入的顺序按顺序执行。所以如果开发中遇到多个线程一个个执行(前一个执行完后,后一个才能执行)的话,可以使用这种方式就可以避免使用join()方法,一个个控制了。

      将上面程序获得线程池的语句修改一下。

//		ExecutorService executorService=Executors.newFixedThreadPool(3);
		ExecutorService executorService=Executors.newSingleThreadExecutor();


运行结果A第1次运行.........
A第2次运行.........
A第3次运行.........
A第4次运行.........
A第5次运行.........
B第1次运行.........
B第2次运行.........
B第3次运行.........
B第4次运行.........
B第5次运行.........
C第1次运行.........
C第2次运行.........
C第3次运行.........
C第4次运行.........
C第5次运行.........
D第1次运行.........
D第2次运行.........
D第3次运行.........
D第4次运行.........
D第5次运行.........

     运行结果是有序的。

     public static ExecutorService newCachedThreadPool()动态创建线程数,如果新加入一个线程任务,当前线程池中没有空闲的线程,则新创建一个线程用来执行新任务;如果有空闲线程,则使用空闲线程。一个线程的任务执行完后,线程状态成为空闲状态,线程不会立即销毁,60秒后,如果没有新任务进来,则空闲线程(空闲时间已达到60s)就销毁.

     将上面程序获取线程池的语句修改下。

//		ExecutorService executorService=Executors.newFixedThreadPool(3);
//		ExecutorService executorService=Executors.newSingleThreadExecutor();
		ExecutorService executorService=Executors.newCachedThreadPool();


运行结果B第1次运行.........
D第1次运行.........
A第1次运行.........
C第1次运行.........
B第2次运行.........
D第2次运行.........
A第2次运行.........
C第2次运行.........
B第3次运行.........
D第3次运行.........
A第3次运行.........
C第3次运行.........
D第4次运行.........
B第4次运行.........
A第4次运行.........
C第4次运行.........
B第5次运行.........
D第5次运行.........
A第5次运行.........
C第5次运行.........

     ABCD的运行是混乱的。

 

       public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize),看方法名就知道,该线程池可以执行定时任务。

package thread;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadPoolTest {
	public static void main(String[] args) {
		ScheduledExecutorService executorService=Executors.newScheduledThreadPool(3);
		MyThread a=new MyThread("A");
		MyThread b=new MyThread("B");
		MyThread c=new MyThread("C");
		MyThread d=new MyThread("D");
		
		
		executorService.schedule(a, 1000, TimeUnit.MILLISECONDS);//1000毫秒后执行
		executorService.schedule(b, 500, TimeUnit.MILLISECONDS);//500ms后执行
		executorService.schedule(c, 1, TimeUnit.SECONDS);//1s后执行
		executorService.schedule(d, 1, TimeUnit.SECONDS);
		
		
		executorService.shutdown();
	}
	
	static class MyThread implements Runnable{
		private String name;
		public MyThread(String name){
			this.name=name;
		}
		@Override
		public void run(){
			for(int i=1;i<=3;i++)
			   System.out.println(name+"在执行第"+i+"次....."+new SimpleDateFormat("hh:mm:ss").format(new Date()));
		}		
	}
}

 

运行结果

B在执行第1次.....08:20:16
B在执行第2次.....08:20:16
B在执行第3次.....08:20:16
A在执行第1次.....08:20:17
A在执行第2次.....08:20:17
A在执行第3次.....08:20:17
C在执行第1次.....08:20:17
C在执行第2次.....08:20:17
C在执行第3次.....08:20:17
D在执行第1次.....08:20:17
D在执行第2次.....08:20:17
D在执行第3次.....08:20:17

         至于public static ScheduledExecutorService newSingleThreadScheduledExecutor(),读者可以将上面程序修改下就OK了。

运行结果

B在执行第1次.....08:25:08
B在执行第2次.....08:25:08
B在执行第3次.....08:25:08
A在执行第1次.....08:25:09
A在执行第2次.....08:25:09
A在执行第3次.....08:25:09
C在执行第1次.....08:25:09
C在执行第2次.....08:25:09
C在执行第3次.....08:25:09
D在执行第1次.....08:25:09
D在执行第2次.....08:25:09
D在执行第3次.....08:25:09

 

 
 
 
 
 
 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值