一.概述
1.1进程与线程
进程:是一个正在执行的程序,每个进程执行都有自己的执行顺序,这就叫程序的执行路径
线程:就是进程中独立的控制单元,一个进程中可以有多个线程,这些线程共享进程的内存,线程控制进程的执行,一个进程中至少有一个线程,多线程之间互不干扰,一个之间出现异常不影响另一个线程的运行,它们各自都有自己的栈,各自管理自己的栈
1.2 创建线程的二种方式
第一种是继承Thread类,实现run方法
public class Demo extends Thread{
Demo(String name){
super(name);
}
public void run(){
//doSomething
}
}
第二种方式是实现Runnable接口
public class Demo implements Runnable{
public void run(){
//doSomething
}
}
public class ThreadDemo{
public static void main(String[] args){
Demo dd=new Demo();
Thread t=new Thread(dd);
t.start();
}
}
二种创建线程的方式区别:继承Thread创建线程的方式不能再继承其它的类,java不支持多继承;实现Runnable接口的方式避免了单继承的局限性;
1.3线程中常用的方法
wait():让线程处于冻结状态,被wait的线程会被存储到线程中
notity():唤醒线程池中一个线程(任意线程)
notityAll():唤醒线程池中的所有线程
sleep():Thread类中的静态方法,线程睡眠
sleep与wait的区别:sleep有时间的限制,当使用sleep时会释放执行权,但是不释放锁;wait是基类Object中的方法,没有时间限制,但使用wait时不仅会释放执行权还会释放锁
2 线程池管理
2.1 线程池的优势
为了我们更好的合理利用线程,Java为我们提供了线程池管理,线程池的优势:
- 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;
- 提高系统响应速度,当有任务到达时,无需等待新线程的创建便能立即执行;
- 方便线程并发数的管控,线程若是无限制的创建,不仅会额外消耗大量系统资源,更是占用过多资源而阻塞系统或oom等状况,从而降低系统的稳定性。线程池能有效管控线程,统一分配、调优,提供资源使用率;
- 更强大的功能,线程池提供了定时、定期以及可控线程数等功能的线程池,使用方便简单
2.2 线程池的用法
Java Api针对不同的场景,为我们提供了4种不同类型的线程池;
newCachedThreadPool:可缓存的线程池,当线程空闲超过60s则会自动回收该线程,线程池的大小没有上限
newFixedThreadPool:一个固定大小的线程池,可指定线程池大小,对于超出的线程会在队列中等待
newScheduledThreadPool:一个可定时执行或周期执行的任务的线程池,可指定线程池核心线程个数
newSingleThreadExecutor:只有一个线程的线程池,所有任务保存在队列中,保证所有任务按照FIFO执行
2.2.1 newCachedThreadPool
创建一个可缓存的无界线程池,该方法无参数。当线程池中的线程空闲时间超过60s则会自动回收该线程,当任务超过线程池的线程数则创建新线程。线程池的大小上限为Integer.MAX_VALUE,可看做是无限大
public void cachedThreadPoolDemo(){
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
final int index = i;
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+", index="+index);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.2.2 newFixedThreadPool
创建一个固定大小的线程池,该方法可指定线程池的固定大小,对于超出的线程会在LinkedBlockingQueue
队列中等待
public void fixedThreadPoolDemo(){
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 6; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+", index="+index);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.2.3 newSingleThreadExecutor
创建一个只有线程的线程池,该方法无参数,所有任务都保存队列LinkedBlockingQueue中,等待唯一的单线程来执行任务,并保证所有任务按照指定顺序(FIFO或优先级)执行
public void singleThreadExecutorDemo(){
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+", index="+index);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.2.4 newScheduledThreadPool
创建一个可定时执行或周期执行任务的线程池,该方法可指定线程池的核心线程个数
public void scheduledThreadPoolDemo(){
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
//定时执行一次的任务,延迟1s后执行
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+", delay 1s");
}
}, 1, TimeUnit.SECONDS);
//周期性地执行任务,延迟2s后,每3s一次地周期性执行任务
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+", every 3s");
}
}, 2, 3, TimeUnit.SECONDS);
}