Java 四种线程池

通常,最开始学Java时,最先接触到线程的就是 Thread 类和 Runnable接口。但是直接用这种方法来实现多线程是有弊端的

弊端:

a. 每次new Thread新建对象性能差。
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。

相比new Thread,Java提供的四种线程池的好处在于:

a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。

Java 线程池

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

1.newCachedThreadPool

创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并 从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。

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

public class ThreadPoolTest {
	
	public static void main(String[] args) {
		
		ExecutorService Pool= Executors.newCachedThreadPool();
		
		for(int i = 0; i < 10; i++) {
			Thread t = new MyThread(i);
			Pool.execute(t);
		}
		Pool.shutdown();
	}
	
}


class MyThread extends Thread {
	
	private int index;
	
	public MyThread(int index) {
		this.index = index;
	}
	
	@Override
	public void run() {
		try {
			System.out.println(Thread.currentThread().getName() + ": " + index);
			Thread.sleep(2000 * index);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

执行结果:

pool-1-thread-3: 2
pool-1-thread-1: 0
pool-1-thread-2: 1
pool-1-thread-4: 3
pool-1-thread-5: 4
pool-1-thread-6: 5
pool-1-thread-7: 6
pool-1-thread-8: 7
pool-1-thread-9: 8
pool-1-thread-10: 9

本次执行的结果,一次性全部输出,可以看出线程容纳了全部十个线程。

2.newFixedThreadPool

创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务, 则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何 线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之 前,池中的线程将一直存在。

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

public class ThreadPoolTest {
	
	public static void main(String[] args) {
		
		ExecutorService Pool= Executors.newFixedThreadPool(5);
		
		for(int i = 0; i < 10; i++) {
			Thread t = new MyThread();
			Pool.execute(t);
		}
		Pool.shutdown();
	}
	
}


class MyThread extends Thread {
	
	@Override
	public void run() {
		try {
			System.out.println(Thread.currentThread().getName());
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

执行结果:

pool-1-thread-2
pool-1-thread-1
pool-1-thread-4
pool-1-thread-3
pool-1-thread-5
pool-1-thread-1
pool-1-thread-2
pool-1-thread-5
pool-1-thread-4
pool-1-thread-3

在执行的时候,会发现前五个是一块输出的,后五个是停了两秒才输出的,证明当线程数达到最大值时,加入的线程是不会运行的。

3、newScheduledThreadPool

创建一个固定大小的线程池。此线程池支持定时以及周期性执行任务的需求。

package demo;

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 Pool = Executors.newScheduledThreadPool(5);
		
		Thread t1 = new MyThread("嘿嘿");
		 // 延时任务
		Pool.schedule(t1, 1, TimeUnit.SECONDS);
		
		Thread t2 = new MyThread("哈哈");
        // 循环任务,按照上一次任务的发起时间计算下一次任务的开始时间
		Pool.scheduleAtFixedRate(t2, 1, 1, TimeUnit.SECONDS);
		
		Thread t3 = new MyThread("哦哦");
        // 循环任务,以上一次任务的结束时间计算下一次任务的开始时间
		Pool.scheduleWithFixedDelay(t3, 1, 5, TimeUnit.SECONDS);
		
	}
	
}


class MyThread extends Thread {
	
	private String msg;
	
	public MyThread(String msg) {
		this.msg = msg;
	}
	
	@Override
	public void run() {
		try {
			System.out.println(Thread.currentThread().getName() + ":" + msg);
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

方法参数
1、schedule

public ScheduledFuture<?> schedule(Runnable command,
                                       long delay, TimeUnit unit);

command:执行线程
delay:初始化延时
unit:计时单位

2、scheduleAtFixedRate

 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
				long initialDelay,
				long period,
				TimeUnit unit);

command:执行线程
initialDelay:初始化延时
period:两次开始执行最小间隔时间
unit:计时单位

3、scheduleWithFixedDelay

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
				long initialDelay,
				long delay,
				TimeUnit unit);

command:执行线程
initialDelay:初始化延时
period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)
unit:计时单位

执行结果:

pool-1-thread-2:哈哈
pool-1-thread-1:嘿嘿
pool-1-thread-3:哦哦
pool-1-thread-1:哈哈
pool-1-thread-1:哈哈
pool-1-thread-5:哈哈
pool-1-thread-4:哦哦
pool-1-thread-3:哈哈
pool-1-thread-3:哈哈
pool-1-thread-3:哈哈
pool-1-thread-4:哦哦
pool-1-thread-3:哈哈
pool-1-thread-3:哈哈
pool-1-thread-4:哈哈
pool-1-thread-4:哈哈
pool-1-thread-2:哦哦
pool-1-thread-3:哈哈
pool-1-thread-3:哈哈
pool-1-thread-5:哈哈

通过结果可以看出,最多只创建了5个线程,schedule方法只执行了一次,其他两个方法每隔一段时间执行一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值