理解java线程池

 

java有四种线程池类型java

单线程线程池缓存

将线程提交到线程池中,提交的线程依次执行安全

Executors.newSingleThreadExecutor()

固定数目线程池多线程

 提交到线程池的任务数大于线程池线程数量则等待函数

Executors.newFixedThreadPool(3)

无界可缓存线程池this

建立的线程数量无上限,第二个任务执行时若第一个任务已执行完则第二个任务执行时复用第一个任务执行时的线程。线程

Executors.newCachedThreadPool()

调度任务线程池code

ScheduledExecutorService  service = Executors.newScheduledThreadPool(3);
service.scheduleAtFixedRate(new MyThread1("线程"+i,i), 1, 1,TimeUnit.SECONDS);
return service;

咱们用简单的代码来看下线程池运行的状况对象

public class executorServiceTest {
	public static int number = 100;
	public static int i =1;
	public static ExecutorService getSingleThreadExecutor() {
		return Executors.newSingleThreadExecutor();

	}
    public static ExecutorService getCachedThreadPool() {
		return Executors.newCachedThreadPool();
	}

	public static ExecutorService getFixedThreadPool() {
		return Executors.newFixedThreadPool(3);
	};

	public static ScheduledExecutorService getScheduledThreadPool() {
		ScheduledExecutorService  service = Executors.newScheduledThreadPool(3);
	    service.scheduleAtFixedRate(new MyThread1("线程"+i,i), 1, 1,TimeUnit.SECONDS);
	    return service;
	};
	
	public static void main(String[] args) {
		// 建立一个可重用固定线程数的线程池
		ExecutorService pool = getSingleThreadExecutor();
	
		// 建立实现了Runnable接口对象,Thread对象固然也实现了Runnable接口
		Thread t1 = new MyThread1("线程1",1);
		t1.setName("线程1");
		Thread t2 = new MyThread1("线程2",2);
		t2.setName("线程2");
		Thread t3 = new MyThread1("线程3,",3);
		t3.setName("线程3");
		Thread t4 = new MyThread1("线程4",4);
		t4.setName("线程4");
		Thread t5 = new MyThread1("线程5",5);
		t5.setName("线程5");
		// 将线程放入池中进行执行  execute没返回值 submit有返回值
		pool.execute(t1);
		pool.execute(t2);
		pool.execute(t3);
		pool.execute(t4);
		pool.execute(t5);
		// 关闭线程池
		pool.shutdown();
	}
}

class MyThread1 extends Thread {
	public void run() {
		System.out.println(Thread.currentThread().getName() + "正在执行。。。");
		executorServiceTest.number =executorServiceTest.number+ this.plusValue;
		executorServiceTest.i = executorServiceTest.i+1;
		System.out.println("加数:"+this.plusValue+",当前number的值:"+executorServiceTest.number);
		
	}

	private String name;
	private int plusValue;

	public MyThread1(String name,int plusValue) {
		super();
		this.name = name;
		this.plusValue = plusValue;
	}

}

上面代码中的前四个静态方法是获取线程池实例接口

MyThread1是线程类 name plusValue 两个属性是为了分析代码构造的 经过构造函数给类的域赋值。

先看看单线程运行池的结果

pool-1-thread-1正在执行。。。
加数:1,当前number的值:101
pool-1-thread-1正在执行。。。
加数:2,当前number的值:103
pool-1-thread-1正在执行。。。
加数:3,当前number的值:106
pool-1-thread-1正在执行。。。
加数:4,当前number的值:110
pool-1-thread-1正在执行。。。
加数:5,当前number的值:115

能够看到线程池里只有一个线程 pool-1-thread-1  执行顺序为1 2 3 4 5
加数:1 表示 执行了提交的t1(参照构造函数)

改变提交顺序

pool.execute(t1);
pool.execute(t3);
pool.execute(t2);
pool.execute(t4);
pool.execute(t5);

结果是这样

pool-1-thread-1正在执行。。。
加数:1,当前number的值:101
pool-1-thread-1正在执行。。。
加数:3,当前number的值:104
pool-1-thread-1正在执行。。。
加数:2,当前number的值:106
pool-1-thread-1正在执行。。。
加数:4,当前number的值:110
pool-1-thread-1正在执行。。。
加数:5,当前number的值:115

只是执行的顺序有改变 1 3 2 4 5

能够单线程线程池是依次执行提交的任务 前一个任务没完成后一个任务不会执行

可缓存线程池

若是线程池的大小超过了处理任务所须要的线程,线程60秒内未使用会被回收 ,若是新的任务被提交,线程池内有未使用的线程则线程会被复用。

提交线程

pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);

第一次执行 

pool-1-thread-1正在执行。。。
加数:1,当前number的值:101
pool-1-thread-3正在执行。。。
加数:3,当前number的值:104
pool-1-thread-5正在执行。。。
加数:5,当前number的值:109
pool-1-thread-2正在执行。。。
加数:2,当前number的值:111
pool-1-thread-4正在执行。。。
加数:4,当前number的值:115

第二次执行

pool-1-thread-3正在执行。。。
加数:3,当前number的值:103
pool-1-thread-1正在执行。。。
加数:1,当前number的值:104
pool-1-thread-5正在执行。。。
加数:5,当前number的值:109
pool-1-thread-2正在执行。。。
加数:2,当前number的值:111
pool-1-thread-4正在执行。。。
加数:4,当前number的值:115

两次执行结果不一样,再执行一次结果还有可能不一样

从这个结果咱们看出线程池内有5个线程(咱们提交了5个任务),线程获得CPU执行机会是随机的。

咱们改变下线程池提交任务的代码(模拟提交任务时线程池内有空闲线程,看是否会被复用)

pool.execute(t1);
pool.execute(t2);
try {
	Thread.sleep(1000);
	} catch (InterruptedException e) {
	// TODO Auto-generated catch block
		e.printStackTrace();
}
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);

这里的Thread.sleep(1000)当前线程休眠1秒后在执行后面的提交t3,t4任务,这时执行t1,t2任务的线程 已经执行完但仍保流在线程池中

下面是运行结果

pool-1-thread-1正在执行。。。
加数:1,当前number的值:101
pool-1-thread-2正在执行。。。
加数:2,当前number的值:103
pool-1-thread-3正在执行。。。
加数:5,当前number的值:108
pool-1-thread-2正在执行。。。
加数:3,当前number的值:111
pool-1-thread-1正在执行。。。
加数:4,当前number的值:115

能够看到线程pool-1-thread-1 pool-1-thread-2被复用了

 

固定数目线程池 运行结果

固定线程池是新来一个任务就会在线程池中建立一个线程,直到达到线程池的数量,线程池的大小一旦达到最大值就会保持不变

好比咱们建立一个数目为3的固定线程池,提交两个任务那么线程池里只会有两个线程

提交的任务超过线程池线程数则等待线程池里的任务执行完

定时任务线程池

同时建立多个定时任务线程池能够用来模拟多线程安全

ScheduledExecutorService  service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new MyThread1("线程"+i,i), 1, 1,TimeUnit.SECONDS);

这里建立的定时任务每1秒执行一次,线程池里只有一个线程。

ScheduledExecutorService  service = Executors.newScheduledThreadPool(3);
service.scheduleAtFixedRate(new MyThread1("线程"+i,i), 1, 1,TimeUnit.SECONDS);

这样线程池里就有3个线程,把3设为1就跟上面的是同样的效果了

相关文章
相关标签/搜索