最近项目比较紧急,固本之旅卡顿了一段时间,抽时间看了一下多线程,面试重点知识!!!
多线程编程
优点:
-
提高程序的响应速度,增加用户的体验;
-
提高计算机系统CPU的利用率;
-
优化程序结构,将一个复杂的单线程分化成多个清晰化的单线程,更有利于维护
并行
指两个以上的事物在同一时刻同时发生在不同的地方(两个厨师各自炒各自的菜)
并发
多个任务在单个处理器上以快速交替的方式执行,给用户一种它们同时发生的错觉。(一个厨师同一时间炒不同的菜,来回快速切换)
线程中常用的方法
run:将需要线程操作的逻辑写进run方法
start:调用run方法,启动线程
currentThread:获取当前执行代码对应的线程
sleep:静态方法,调用时可以使当前线程睡眠指定毫秒数
yield:释放cpu的执行权
join:在线程A中通过线程B调用Join方法,意味着A进入阻塞状态,直到线程B执行结束在执行
isAlive:判断当前线程是否存活
创建多线程的四种方式
1:继承Thread基类,实现起来较为简单,但是局限性比较大,无法获得异常信息,返回值,而且由于JAVA是单继承的,继承Thread基类会影响当前类的可扩展性,不利于后续代码优化编写。
package com.yxb.security.demo.service.serviceImpl;
class ThreadService extends Thread {
/**
* @Description:
* @author : loong
* @Date: 2024-08-31
*/
private Boolean falg;
public ThreadService(Boolean falg) {
this.falg = falg;
}
@Override
public void run() {
for (int i = 1; i < 100; i++) {
if (falg == false && i % 2 == 0) {
System.out.println("双数"+i);
}else if (falg == true && i % 2 != 0){
System.out.println("单数"+i);
}
}
}
}
public class ThreadExample {
public static void main(String[] args) {
ThreadService threadService = new ThreadService(false);
threadService.start();
ThreadService threadService1 = new ThreadService(true);
threadService1.start();
}
}
2:实现runnable接口
-
通过实现runnable接口实现多线程,我们成功解决了java单继承的问题,因为JAVA是可以实现多个接口的,为代码的可延伸性提供了保障;
-
更适合处理有共享数据的问题,我们可以通过多个线程调用同一个对象保证数据的一致性;
-
实现了代码和数据的有效分离;
package com.yxb.security.demo.service.serviceImpl;
class ThreadService implements Runnable {
public ThreadService(Boolean falg) {
this.falg = falg;
}
/**
* @Description:
* @author : loong
* @Date: 2024-08-31
*/
private Boolean falg;
@Override
public void run() {
for (int i = 1; i < 100; i++) {
if (falg == false && i % 2 == 0) {
System.out.println("双数"+i);
}else if (falg == true && i % 2 != 0){
System.out.println("单数"+i);
}
}
}
}
class RunnableDemo{
public static void main(String[] args) {
ThreadService threadService = new ThreadService(true);
Thread thread = new Thread(threadService);
thread.start();
Thread thread1 = new Thread(threadService);
thread1.start();
}
}
实现Callable接口:
-
可以获得返回值
-
可以通过throws的方式解决异常
-
使用了泛型参数,可以指明call的返回值类型,更加灵活
创建线程池:
-
提高了程序执行的效率(线程已经提前创建)
-
提高了资源的复用率(线程执行完并未直接销毁,可以继续执行其他任务)
-
有相关的参数,可以对线程池中的参数进行有效管理
线程池的七大参数:核心线程数,最大线程数,非核心线程空闲时间,时间单位,阻塞队列,线程工厂,拒绝策略
线程池执行流程:当请求来的时候先判断核心线程数是否已满(即便当前有空闲的核心线程,但是如果未达到核心线程数仍会创建处理),如果未满直接创建核心线程,如果已满则在判断队列是否满,如果未满,请求进入队列中,如果队列也满的话再判断,当前线程数是否到达最大线程数,如果没到达则直接创建非核心线程,如果当前线程数到了最大线程数则执行拒绝策略(默认抛出异常)。
package com.yxb.security.demo.service.serviceImpl;
import java.util.concurrent.*;
public class ThreadPools {
/**
* @Description:
* @author : loong
* @Date: 2024-08-31
*/
public static void main(String[] args) {
/*线程池七大核心参数*/
/*从上往下是核心线程数,最大线程数,非核心线程空闲时间,时间单位,阻塞队列,线程工厂,拒绝策略*/
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5,
30,
20L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
for (int i = 0; i < 20; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
}
}