目录
1、NEW:新建状态,新创建的线程,此时尚未调用start()方法;
2、Runnable:运行状态,运行中的线程,已经调用start()方法,线程正在或即将执行run()方法;
3、Blocked:阻塞状态:运行中的线程,在等待竞争锁时,被阻塞,暂不执行;
4、Waiting:等待状态,运行中的线程,因为join()wait()等方法调用,进入等待。 notify() notifyAll()方法唤醒线程 -- 锁对象让等待的对象唤醒
5、TimedWaiting:计时等待状态,计时等待状态,运行中的线程,因为执行sleep(等待毫秒值)join(等待毫秒值)等方法,进入计时等待;
6、Terminated:终止状态,终止状态,线程已终止,因为run()方法执行完毕。
(2)ReentrantReadWriteLock.ReadLock:读锁
(3)ReentrantReadWriteLock.WriteLock:写锁
(1)lock():获取锁,如果锁被其他线程持有,则当前线程会阻塞
(2)lockInterruptibly():获取锁,但可以被中断
(3)tryLock():尝试获取锁,立即返回,获取成功返回true,否则返回false
(4)tryLock(long time, TimeUnit unit):在指定时间内尝试获取锁
(6)newCondition():创建一个与该锁相关联的Condition对象
(1)ExecutorService接口:进行线程池的操作访问;
(3)ThreadPoolExecutor及其子类:封装线程池的核心参数和运行机制;
(1)shutdown()方法关闭线程池的时候,它会等待正在执行的任务先完成,然后再关闭。
(1)newFixedThreadPool(int nThreads ):通过工具类获取线程池对象 有上限
(2)newCachedThreadPool():线程数根据任务动态调整的线程池,创建一个线程数量无上限的线程池对象
(3)newSingleThreadExecutor():仅提供一个单线程的线程池
(4)newScheduledThreadPool():能实现定时,周期性任务的线程池
4、使用ThreadPoolExecutor类创建线程池对象:
(1)、创建线程池对象:ExecutorService es = new ThreadPoolExecutor( .......);
(1.2)int maximumPoolSize, 最大线程数(核心+非核心(临时))
(1.3) long keepAliveTime, 临时线程最大存活时间
(1.5)BlockingQueue workQueue, 等待队列
(1.6)ThreadFactory threadFactory, 线程工厂 创建线程
(1.7)RejectedExecutionHandler handler 拒绝策略
(3)降低资源消耗(线程执行充任务,不销毁,可以执行其他的年务)
(1.2)非核心线程线程空闲存活时间,即keepAliveTime为0
(1.3)阻塞队列为无界队列LinkedBlockingQueue
(2.3)如果线程数等于核心线程,把任务添加到LinkedBlockingQueue阻塞队列
(3)使用场景: 适用于处理CPU密集型的任务,确保CPU在长期被工作线程使用的情况下,尽可能的少的分配线程,即适用执行长期的任务。
(1.2)最大线程数为Integer.MAX_VALUE
(1.3)工作队列是SynchronousQueue同步队列
(2.2)因为核心线程数为0,所以任务直接加到SynchronousQueue工作队列
(2.5)执行完任务的线程,还可以存活60秒,如果在这期间,接到任务,可以继续存活下去;否则,被销毁。
3、SingleThreadExecutor:单线程化的线程池
(2)使用场景: 适用于串行执行任务的场景,将任务按顺序执行。
4、ScheduledThreadPool:能实现定时、周期性任务的线程池
(2)使用场景: 周期性执行任务,并且需要限制线程数量的需求场景。
一、线程的状态:
在Java程序中,一个线程对象通过调用start()方法启动线程,并且在线程获取CPU时,自动执行run()方法。run()方法执行完毕,代表线程的生命周期结束。整个线程的生命周期中,线程的状态有以下6种:
1、NEW:新建状态,新创建的线程,此时尚未调用start()方法;
public class Demo01 {
//NEW:新建状态,新创建的线程,此时尚未调用start()方法
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
System.out.println("正在执行某个任务");
}
};
System.out.println(t1.getState());
}
}
2、Runnable:运行状态,运行中的线程,已经调用start()方法,线程正在或即将执行run()方法;
public class Demo02 {
//RUNNABLE运行状态,运行中的线程,已经调用户start()方法,线程正在或即将执行run方法
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println("正在执行某个任务");
}
}
};
System.out.println(t1.getState());
}
}
3、Blocked:阻塞状态:运行中的线程,在等待竞争锁时,被阻塞,暂不执行;
package com.yuan.state;
public class Demo04 {
public static void main(String[] args) throws InterruptedException {
Object obj=new Object();
Runnable r1 = new Runnable(){
@Override
public void run() {
synchronized (obj){
while (true){
//死循环,只能执行一个,另一个等待
}
}
}
};
Thread t1 = new Thread(r1, "线程1:");
Thread t2 = new Thread(r1, "线程2:");
t1.start();
t2.start();
//让主线程休眠,让t1和t2同时竞争一个锁资源 有一个会阻塞
Thread.sleep(100);
System.out.println(t1.getName()+t1.getState());
System.out.println(t2.getName()+t2.getState());
}
}
4、Waiting:等待状态,运行中的线程,因为join()wait()等方法调用,进入等待。 notify() notifyAll()方法唤醒线程 -- 锁对象让等待的对象唤醒
package com.yuan.state;
public class Demo06 {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
Runnable r1 = new Runnable() {
@Override
public void run() {
synchronized (obj) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t1 = new Thread(r1, "线程1:");
t1.start();
Thread.sleep(100);
System.out.println(t1.getName() + t1.getState());
}
}
5、TimedWaiting:计时等待状态,计时等待状态,运行中的线程,因为执行sleep(等待毫秒值)join(等待毫秒值)等方法,进入计时等待;
package com.yuan.state;
public class Demo05 {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
Runnable r1 = new Runnable(){
@Override
public void run() {
synchronized (obj){
try {
//Thread.sleep(1000*5) //不释放
obj.wait(1000*5); //释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t1 = new Thread(r1, "线程1:");
Thread t2 = new Thread(r1, "线程2:");
t1.start();
t2.start();
//让主线程休眠,让t1和t2同时竞争一个锁资源
Thread.sleep(100);
System.out.println(t1.getName()+t1.getState());
System.out.println(t2.getName()+t2.getState());
}
}
6、Terminated:终止状态,终止状态,线程已终止,因为run()方法执行完毕。
public class Demo03 {
public static void main(String[] args) throws InterruptedException {
//Terminated:终止状态,线程已终止,因为run()方法执行完毕
Thread t1 = new Thread(){
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println("正在执行某个任务");
}
}
};
t1.start();
//等待t1执行完毕,执行mian线程
Thread.sleep(1000);
System.out.println(t1.getState());
}
}

二、lock锁:
在 Java 中,Lock是 Java 5 引入的一个接口,位于java.util.concurrent.locks包下,它提供了比synchronized关键字更灵活、更强大的线程同步机制。
1、Lock接口的主要实现类:
(1)ReentrantLock:可重入锁,最常用的实现类
(2)ReentrantReadWriteLock.ReadLock:读锁
(3)ReentrantReadWriteLock.WriteLock:写锁
2、核心方法:
(1)lock():获取锁,如果锁被其他线程持有,则当前线程会阻塞
(2)lockInterruptibly():获取锁,但可以被中断
(3)tryLock():尝试获取锁,立即返回,获取成功返回true,否则返回false
(4)tryLock(long time, TimeUnit unit):在指定时间内尝试获取锁
(5)unlock():释放锁
(6)newCondition():创建一个与该锁相关联的Condition对象
package com.yuan.lock;
import java.util.Hashtable;
public class DeadLock {
private static Object obj1=new Object();
private static Object obj2=new Object();
public void add() throws InterruptedException {
synchronized (obj1){
System.out.println("进入到add方法中");
Thread.sleep(1000);
synchronized (obj2){
System.out.println("add方法执行结束");
}
}
}
public void desc() throws InterruptedException {
synchronized (obj2){
System.out.println("进入到desc方法中");
Thread.sleep(1000);
synchronized (obj1){
System.out.println("desc方法执行结束");
}
}
}
}
class Demo02 {
public static void main(String[] args) throws InterruptedException {
DeadLock dl = new DeadLock();
Thread t1 = new Thread(){
@Override
public void run() {
try {
dl.add();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread(){
@Override
public void run() {
try {
dl.desc();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t1.start();
Thread.sleep(1000*2);
t2.start();
}
}
三、线程池:
线程池内部维护了若干个线程,没有任务的时候,这些线程都处于等待空闲状态。如果有新的线程任务,就分配一个空闲线程执行。如果所有线程都处于忙碌状态,线程池会创建一个新线程进行处理或者放入队列(工作队列)中等待。
1、线程池的常用类和接口:
(1)ExecutorService接口:进行线程池的操作访问;
(2)Executors类:创建线程池的工具类;
(3)ThreadPoolExecutor及其子类:封装线程池的核心参数和运行机制;
2、关闭线程池:
(1)shutdown()方法关闭线程池的时候,它会等待正在执行的任务先完成,然后再关闭。
(2)shutdownNow()会立刻停止正在执行的任务;
(3)awaitTermination()方法时,主线程会处于一种等待的状态,按照指定的timeout检查线程池。第一个参数指定的是时间,第二个参数指定的是时间单位(当前是秒)。返回值类型为boolean型。该方法经常与shutdown()方法配合使用,用于检测线程池中的任务是否已经执行完毕:
3、使用Executors工具类创建线程池对象:
package com.yuan.executor;
public class MyRun implements Runnable {
String str;
public MyRun(String str) {
this.str = str;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行" + str);
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "结束执行任务" + str);
}
}
(1)newFixedThreadPool(int nThreads ):通过工具类获取线程池对象 有上限
public class Demo01 {
public static void main(String[] args) throws InterruptedException {
//通过工具类获取线程池对象 有上限
ExecutorService es= Executors.newFixedThreadPool(3);
//2、提交任务给线程池对象
es.execute(new MyRun("任务1"));
es.execute(new MyRun("任务2"));
es.execute(new MyRun("任务3"));
Thread.sleep(1000);
es.execute(new MyRun("任务4"));
//3、线程池的关闭方法
es.shutdown(); //1、会等待正在执行的任务先完成,然后再关闭
// es.shutdownNow(); //2、会立刻停止正在执行的任务
//每隔1毫秒检查一次线程池的任务执行状态
while(!es.awaitTermination(1, TimeUnit.SECONDS)){
System.out.println("还没有关闭线程池");
}
System.out.println("已经关闭线程池");
}
}
(2)newCachedThreadPool():线程数根据任务动态调整的线程池,创建一个线程数量无上限的线程池对象
public class Demo02 {
public static void main(String[] args) throws InterruptedException {
//创建一个线程数量无上限的线程池对象
ExecutorService es = Executors.newCachedThreadPool();
//循环的提交任务
for (int i = 0; i <=9 ; i++) {
es.execute(new MyRun("任务"+i));
}
Thread.sleep(1000*7);
es.execute(new MyRun("最后的一个任务"));
es.shutdown();
}
}
(3)newSingleThreadExecutor():仅提供一个单线程的线程池
public class Demo03 {
public static void main(String[] args) {
//newSingleThreadExecutor():仅提供一个单线程的线程池
ExecutorService es = Executors.newSingleThreadExecutor();
for (int i = 0; i <=9; i++) {
es.execute(new MyRun("任务"+i));
}
es.shutdown();
}
}
(4)newScheduledThreadPool():能实现定时,周期性任务的线程池
public class Demo04 {
public static void main(String[] args) {
//能实现定时,周期性任务的线程池
ScheduledExecutorService es = Executors.newScheduledThreadPool(2);
Runnable r1 = new Runnable(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在执行");
}
};
//2.提交任务--延时多久进行任务的执行
// command-任务对象,delay-延时的时间,unit-时间单位
// es.schedule(r1,2,Timeunit.SECONDS);
// scheduleAtFixedRate延时2秒首次执行此任务,每隔5秒进行此任务的执行
es.scheduleAtFixedRate(r1,0,5,TimeUnit.SECONDS);
// scheduleWithFixedDelay,上一次任务执行完毕后,等待固定的时间间隔,再执行下一次任务;
// es.scheduleWithFixedDelay(r1,0,3, TimeUnit.SECONDS);
// 线程池进行资源关闭
// es.shutdown();
}
}
4、使用ThreadPoolExecutor类创建线程池对象:
(1)、创建线程池对象:ExecutorService es = new ThreadPoolExecutor( .......);
参数类型:
(1.1) int corePoolSize, 核心线程数
(1.2)int maximumPoolSize, 最大线程数(核心+非核心(临时))
(1.3) long keepAliveTime, 临时线程最大存活时间
(1.4) TimeUnit unit, 存活的时间单位
(1.5)BlockingQueue<Runnable> workQueue, 等待队列
(1.6)ThreadFactory threadFactory, 线程工厂 创建线程
(1.7)RejectedExecutionHandler handler 拒绝策略
------ThreadPoolExecutor.AbortPolicy()默认拒绝策略 抛出异常 *
------ThreadPoolExecutor.DiscardOldestPolicy() 扔掉队列等待时间最长的任务
------ThreadPoolExecutor.DiscardPolicy() 丢弃最后一个
------ThreadPoolExecutor.CallerRunsPolicy() 让现在正在执行的线程执行 main
public class Demo01 {
public static void main(String[] args) {
ExecutorService es = new ThreadPoolExecutor(
3,
5,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
es.submit(new MyRun("任务1")); //提及送一个任务给es对象
es.submit(new MyRun("任务2"));
es.submit(new MyRun("任务3"));
es.submit(new MyRun("任务4"));//核心线程已满,进入等待队列
es.submit(new MyRun("任务5"));
es.submit(new MyRun("任务6"));
es.submit(new MyRun("任务7"));//等待队列已满,使用临时线程
es.submit(new MyRun("任务8"));
es.submit(new MyRun("任务9"));//核心,等待,临时都已满,默认拒绝策略,抛出异常报错
es.submit(new MyRun("任务10"));
}
}
class MyRun implements Runnable {
String str;
public MyRun(String str) {
this.str = str;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行" + str);
// while (true){
// //死循环
// }
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "结束执行任务" + str);
}
}
5、线程池的优点:
(1)提高响应的速度
(2)提高线程的可管理性
(3)降低资源消耗(线程执行充任务,不销毁,可以执行其他的年务)
四、线程池分类总结:
1、FixedThreadPool:
(1)线程池参数:
(1.1)核心线程数和最大线程数一致
(1.2)非核心线程线程空闲存活时间,即keepAliveTime为0
(1.3)阻塞队列为无界队列LinkedBlockingQueue
(2)工作机制:
(2.1)提交线程任务
(2.2)如果线程数少于核心线程,创建核心线程执行任务
(2.3)如果线程数等于核心线程,把任务添加到LinkedBlockingQueue阻塞队列
(2.4)如果线程执行完任务,去阻塞队列取任务,继续执行
(3)使用场景: 适用于处理CPU密集型的任务,确保CPU在长期被工作线程使用的情况下,尽可能的少的分配线程,即适用执行长期的任务。
2、CachedThreadPool:
(1)线程池参数:
(1.1)核心线程数为0
(1.2)最大线程数为Integer.MAX_VALUE
(1.3)工作队列是SynchronousQueue同步队列
(1.4)非核心线程空闲存活时间为60秒
(2)工作机制:
(2.1)提交线程任务
(2.2)因为核心线程数为0,所以任务直接加到SynchronousQueue工作队列
(2.3)判断是否有空闲线程,如果有,就去取出任务执行
(2.4)如果没有空闲线程,就新建一个线程执行
(2.5)执行完任务的线程,还可以存活60秒,如果在这期间,接到任务,可以继续存活下去;否则,被销毁。
(3)使用场景: 用于并发执行大量短期的小任务。
3、SingleThreadExecutor:单线程化的线程池
(1)线程池参数:
(1.1)核心线程数为1
(1.2)最大线程数也为1
(1.3)阻塞队列是LinkedBlockingQueue
(1.4)非核心线程空闲存活时间为0秒
(2)使用场景: 适用于串行执行任务的场景,将任务按顺序执行。
4、ScheduledThreadPool:能实现定时、周期性任务的线程池
(1)线程池参数:
(1.1)最大线程数为Integer.MAX_VALUE
(1.2)阻塞队列是DelayedWorkQueue
(1.3)keepAliveTime为0
(2)使用场景: 周期性执行任务,并且需要限制线程数量的需求场景。
四、线程池注意事项:
在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了资源的开销。而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式。jdk中Executor框架虽然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()等创建线程池的方法,但都有其局限性,不够灵活;另外由于前面几种方法内部也是通过new ThreadPoolExecutor方式实现,使用ThreadPoolExecutor有助于大家明确线程池的运行规则,创建符合自己的业务场景需要的线程池,避免资源耗尽的风险。
必须为线程池中的线程,按照业务规则,进行命名。可以在创建线程池时,使用自定义线程工厂规范线程命名方式,避免线程使用默认名称

被折叠的 条评论
为什么被折叠?



