线程
线程是调度CPU资源的最小单位,线程模型分为KLT模型与ULT模型,JVM使用的KLT模
型,Java线程与OS线程保持1:1的映射关系,也就是说有一个java线程也会在操作系统里有一个对应的线程。Java线程有多种生命状态
NEW,新建
RUNNABLE,运行
BLOCKED,阻塞
WAITING,等待
TIMED_WAITING,超时等待
TERMINATED,终结
状态切换如下图所示:
协程
协程 (纤程,用户级线程),目的是为了追求最大力度的发挥硬件性能和提升软件的速度,协程基本原理是:在某个点挂起当前的任务,并且保存栈信息,去执行另一个任
务;等完成或达到某个条件时,再还原原来的栈信息并继续执行(整个过程线程不需要 上下文切换)。
Java原生不支持协程,在纯java代码里需要使用协程的话需要引入第三方包,如:quasar
线程池
“线程池”,顾名思义就是一个线程缓存,线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,因此Java中提供线程池对线程进行统一分配、调优和监控
线程池介绍
在web开发中,服务器需要接受并处理请求,所以会为一个请求来分配一个线程来进行处理。如果每次请求都新创建一个线程的话实现起来非常简便,但是存在一个问题:
如果并发的请求数量非常多,但每个线程执行的时间很短,这样就会频繁的创建和销毁线程,如此一来会大大降低系统的效率。可能出现服务器在为每个请求创建新线程和销毁线
程上花费的时间和消耗的系统资源要比处理实际的用户请求的时间和资源更多。
那么有没有一种办法使执行完一个任务,并不被销毁,而是可以继续执行其他的任务呢?
这就是线程池的目的了。线程池为线程生命周期的开销和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。
什么时候使用线程池?
- 单个任务处理时间比较短需要处理的任务数量很大
- 需要处理的任务数量很大
线程池优势
- 重用存在的线程,减少线程创建,消亡的开销,提高性能
- 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资
- 源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
线程的实现方式
Thread,Runnable,Callable
方式一:继承Thread类,并重写run方法
注意:开启线程要使用start()方法,run()方法只是普通的方法调用。
实际上的创建线程还是通过本地方法,Java本身并不能开启线程。
方式二:实现Runnable接口,并重写run方法
注意:这里要通过Thread对象来开启线程。
方式三:实现Callable接口,并重写call方法
注意:因为要通过Thread对象来开启线程,上面给出了Thread类的构造方法,没有直接的方法可以传入Callable,所以我们要对其进行加功。而Callable又是特别的,它可以有返回值。所以提供了一个FutureTask类,通过它可以获取返回的结果。且它间接实现了Runnable接口,所以可以传入Thread的构造函数。如下:
方式四:通过线程池创建
package orange;
import java.util.concurrent.*;
public class MyThread4 {
public static void main(String[] args) {
/**
* 高速缓存的线程池,需要多少创建多少,60s未调用就会自动销毁。
* ThreadPoolExecutor(0, Integer.MAX_VALUE,
* 60L, TimeUnit.SECONDS,
* new SynchronousQueue<Runnable>())
*/
ExecutorService executorService = Executors.newCachedThreadPool();
/**
* 固定大小的线程池,满了就等待
* ThreadPoolExecutor(nThreads, nThreads,
* 0L, TimeUnit.MILLISECONDS,
* new LinkedBlockingQueue<Runnable>())
*/
ExecutorService executorService1 = Executors.newFixedThreadPool(10);
/**
* 每次只创建一个线程,满了就等待
* new ThreadPoolExecutor(1, 1,
* 0L, TimeUnit.MILLISECONDS,
* new LinkedBlockingQueue<Runnable>()))
*/
ExecutorService executorService2 = Executors.newSingleThreadExecutor();
/**
* 自定义线程池
* ThreadPoolExecutor(int corePoolSize, //核心线程数
* int maximumPoolSize, //最大线程数
* long keepAliveTime, //非核心线程空闲时的存活时间
* TimeUnit unit, //存活时间单位
* BlockingQueue<Runnable> workQueue, //阻塞队列,也就是等着获取线程的
* ThreadFactory threadFactory, //线程工厂
* RejectedExecutionHandler handler) //拒绝策略,默认为AbortPolicy()
*/
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10,
20L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
executorService.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "线程执行了");
}
});
executorService1.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "线程执行了");
}
});
executorService2.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "线程执行了");
}
});
threadPoolExecutor.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "线程执行了");
}
});
executorService.shutdown();
executorService1.shutdown();
executorService2.shutdown();
threadPoolExecutor.shutdown();
}
}