这一篇博文是【大数据技术●降龙十八掌】系列文章的其中一篇,点击查看目录:大数据技术●降龙十八掌
- 系列文章:
-
【十八掌●基本功篇】第一掌:Java之IO
【十八掌●基本功篇】第一掌:Java之多线程–1-一些概念
【十八掌●基本功篇】第一掌:Java之多线程–2-join、同步、死锁、等待
【十八掌●基本功篇】第一掌:Java之多线程–3-线程池
线程池的基本思想是开辟一块内存空间,里面存放了很多的线程,池中的线程执行调度由池管理器来处理,当有线程任务时,从池中取一个线程,自行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省系统的资源。
线程池的好处一是通过重复利用已经存在的线程,降低了频繁创建和销毁线程所带来的消耗,因为不用等待创建线程,也提高了程序响应速度。二是线程池统一对线程进行分配和监控,提高了线程的可管理性,也控制了线程的总数,不会无限制地创建线程。
(1) 常见线程池
举个例子:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by 鸣宇淳 on 2017/12/12.
*/
public class Demo1 {
public static void main(String[] args) {
//三种线程池
// 1.创建一个固定大小的线程池,
//ExecutorService pool= Executors.newFixedThreadPool(3);
// 2.创建一个单个worker线程的Executors,保证多个线程以指定的顺序执行
//ExecutorService pool=Executors.newSingleThreadExecutor();
// 3.创建一个可根据需要创建新线程池。
ExecutorService pool=Executors.newCachedThreadPool();
//创建多个线程
Thread t1=new Thread(new MyThread("线程1"));
Thread t2=new Thread(new MyThread("线程2"));
Thread t3=new Thread(new MyThread("线程3"));
Thread t4=new Thread(new MyThread("线程4"));
Thread t5=new Thread(new MyThread("线程5"));
Thread t6=new Thread(new MyThread("线程6"));
//将线程放入池中执行,向线程池中投放任务
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
pool.execute(t6);
//关闭线程池
pool.shutdown();
}
}
/**
* Created by 鸣宇淳 on 2017/12/12.
*/
public class MyThread implements Runnable {
private String name = "";//线程的名字
public MyThread(String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(500);
System.out.println(name + ":正在执行" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这个例子中可以看到:
第一种:定义了一个3个大小的线程池,放入6个线程执行,是前三个先执行,有一个执行完毕后,再执行剩下的,最多有三个线程在执行。
第二种:线程是根据设置的顺序,依次执行的,没有并发的状态。
第三种:会根据运行时的需要,按需创建新的线程。
(2) 延迟线程池
延迟线程池可以设置多长时间后执行某一个线程。
具体看以下实例:
import java.util.Date;
/**
* Created by 鸣宇淳 on 2017/12/13.
*/
public class ScheduledThreadDemo {
public static void main(String[] args) {
//创建一个延时线程池
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
Thread t1 = new Thread(new MyThread2("线程1"));
Thread t2 = new Thread(new MyThread2("线程2"));
Thread t3 = new Thread(new MyThread2("线程3"));
Thread t4 = new Thread(new MyThread2("线程4"));
System.out.println("开始运行时间:" + new Date() + "\n================");
pool.execute(t1);
pool.execute(t2);
//延时5秒后,执行线程t3
pool.schedule(t3, 5, TimeUnit.SECONDS);
//延时10秒后,执行线程t4
pool.schedule(t4, 10, TimeUnit.SECONDS);
pool.shutdown();
}
}
public class MyThread2 implements Runnable {
private String name = "";//线程的名字
public MyThread2(String name) {
this.name = name;
}
public void run() {
System.out.println(new Date() + "_" + name + ":正在执行");
}
}
输出为:
开始运行时间:Wed Dec 13 08:39:13 CST 2017
================
Wed Dec 13 08:39:13 CST 2017_线程1:正在执行
Wed Dec 13 08:39:13 CST 2017_线程2:正在执行
Wed Dec 13 08:39:18 CST 2017_线程3:正在执行
Wed Dec 13 08:39:23 CST 2017_线程4:正在执行
(3) 自定义线程池
举个例子:
/**
* Created by 鸣宇淳 on 2017/12/13.
*/
public class CustomThreadPool {
public static void main(String[] args) {
//创建队列
BlockingQueue<Runnable> bqueue=new ArrayBlockingQueue<Runnable>(20);
//创建一个自定义的线程池
// 1.第一个参数是池中保存的核心线程数
// 2.第二个参数是池中允许的最大线程数
// 3.第三个参数是:线程池维护线程所允许的空闲时间。
// 当线程池中的线程数量大于corePoolSize的时候,
// 如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,
// 直到等待的时间超过了keepAliveTime
// 4.第四个参数为时间单位
// 5.第五个参数是用于保存线程任务的队列。
ThreadPoolExecutor pool=new ThreadPoolExecutor(2,5,1000, TimeUnit.MILLISECONDS,bqueue);
Thread t1 = new Thread(new MyThread2("线程1"));
Thread t2 = new Thread(new MyThread2("线程2"));
Thread t3 = new Thread(new MyThread2("线程3"));
Thread t4 = new Thread(new MyThread2("线程4"));
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.shutdown();
}
}