java 线程池简介

线程池简介


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

         使用线程池的原因
                1.减少创建和销毁线程的次数,每个工作线程都可以重复的被利用,可执行多个任务。
                2.由于线程池中线程数量可以调节,能够很方便的找到适应系统的最高效的工作方式。

         在Java里面的线程池顶级接口是Executor,但是严格来说它并不是一个线程池,只是一个用来执行线程的工具,真正的线程池接口是ExecutorService.
         下面介绍几个和线程池有关的类:
         ExecutorService: 真正的线程池接口。

              ScheduledExecutorService: 能和Timer以及TimerTask类似,具有定时重复执行任务的功能。

         ThreaadPoolExecutor: ExecutorService的默认实现。

         ScheduledThreadPoolExecutor:   继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。

         由于线程池的性能和其中的最大线程数与系统的匹配相关联,所以对于一般人来说,原理了解的不是很清楚,配出来的线程池的性能也不高,在Executors类中提供了一些静态工厂,可以帮助我们生成一些常用的线程池。

         1.newSingleThreadExecutor() : 创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串执行所有任务。

         2.newFixedThreadPool() : 创建固定大小的线程池。每次向线程池提交一个任务就创建一个县城,直到线程数量达到线程池的最大值,一旦达到了最大值就会保持不变,如果线程池中某个线程异常结束了,线程池会新增一个线程来补充。

         3.newCachedThreadPool() : 创加一个可缓存的线程池,如果当前线程池中线程数量小于最大值,线程池会自动的回收部分空闲(60秒不执行任务)的线程,当任务数量变多,线程池再添加新的现车呢个来执行处理任务。这个线程池的大小没做限制,完全取决于该系统的承受能力。

         4.newScheduledThreadPool() : 创建一个大小无线的线程池,这个线程池支持定时任务以及周期性执行任务。

             上面介绍了这些东西,下面就来挨个试一试:
SingleThreadExecutor

public class ThreadPoolTest {

	public static void main(String[] args) {
		//创建一个单线程的线程池
		ExecutorService pool = Executors.newSingleThreadExecutor();
		//创建实现了Runnable接口的对象
		Thread t1 = new TestThread();
		Thread t2 = new TestThread();
		Thread t3 = new TestThread();
		Thread t4 = new TestThread();
		Thread t5 = new TestThread();
		//将线程放入池中进行执行
		pool.execute(t1);
		pool.execute(t2);
		pool.execute(t3);
		pool.execute(t4);
		pool.execute(t5);
		//关闭线程池
		pool.shutdown();
	}

}

class TestThread extends Thread {
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + "正在执行...");
	}
}

         上面的代码创建了一个单线程的线程池,只有一个线程工作,所以往线程池中加入5个任务,也只是用一个线程在跑,一个任务执行的时候其他任务在队列中处于等待状态。


FixedThreadPool

public class ThreadPoolTest {

	public static void main(String[] args) {
		//创建一个固定大小为2的线程池
		ExecutorService pool = Executors.newFixedThreadPool(2);
		//创建实现了Runnable接口的对象
		Thread t1 = new TestThread();
		Thread t2 = new TestThread();
		Thread t3 = new TestThread();
		Thread t4 = new TestThread();
		Thread t5 = new TestThread();
		//将线程放入池中进行执行
		pool.execute(t1);
		pool.execute(t2);
		pool.execute(t3);
		pool.execute(t4);
		pool.execute(t5);
		//关闭线程池
		pool.shutdown();
	}

}

class TestThread extends Thread {
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + "正在执行...");
	}
}



线程池中有两个线程可以执行任务,往里面加入五个可执行任务,线程池会自动的将自动分配给两个线程去运行,我们能看到结果可能会不同,有时候线程1运行的任务要多一些,有时候会差不多。


CachedThreadPool

public class ThreadPoolTest {


	public static void main(String[] args) {
		//创建一个可缓冲的线程池,能自动的根据需求调整线程池中的线程数量
		ExecutorService pool = Executors.newCachedThreadPool();
		//创建实现了Runnable接口的对象
		Thread t1 = new TestThread();
		Thread t2 = new TestThread();
		Thread t3 = new TestThread();
		Thread t4 = new TestThread();
		Thread t5 = new TestThread();
		//将线程放入池中进行执行
		pool.execute(t1);
		pool.execute(t2);
		pool.execute(t3);
		pool.execute(t4);
		pool.execute(t5);
		//关闭线程池
		pool.shutdown();
	}

}

class TestThread extends Thread {
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + "正在执行...");
	}
}




我们基本上是在同时加入了5个任务,所以线程池快速的反应并创建了5个线程来执行任务,时间差很微小,可能由于打印的时间不一样,打印的顺序可能会有所不同,而这些任务执行时间都很短,如果在第一个任务执行完了,第五个任务刚加入的时候,线程池就不会再创建第五个线程了,而是用空闲出来的第一个线程来执行第5个任务,会出现如下图的情况:




4.ScheduleThreadpool

public class ThreadPoolTest {




<span style="white-space:pre">	</span>public static void main(String[] args) {
<span style="white-space:pre">		</span>//创建一个能执行定时任务的线程池
<span style="white-space:pre">		</span>ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(2);
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>exec.scheduleAtFixedRate(new Runnable() {//每隔一段时间就触发异常
            @Override
            public void run() {
                 //throw new RuntimeException();
                 System.out.println(Thread.currentThread().getName() + "================");
            }
        }, 1000, 5000, TimeUnit.MILLISECONDS);
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>exec.scheduleAtFixedRate(new Runnable() {//每隔一段时间打印系统时间,证明两者是互不影响的
            @Override
            public void run() {
                 System.out.println(Thread.currentThread().getName() + System.nanoTime());
            }
        }, 1000, 2000, TimeUnit.MILLISECONDS);
<span style="white-space:pre">	</span>}


}



在这个只有一个线程的可定时执行任务的线程池中,存放着两个定时任务,但从结果可以看到,打印时间的任务还是每隔2秒执行一次,没有受到另外一个定时任务的影响。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值