文章目录

  • 一、多线程创建
  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口
  • 二、线程优先级
  • 三、线程同步
  • 同步方法
  • 同步代码块
  • 深入理解synchronized底层原理
  • 四、死锁
  • 五、线程池
  • 线程池说明
  • Bean方式创建异步线程池
  • 可缓存线程池:newCachedThreadPool
  • 定长线程池:newFixedThreadPool
  • 定时及周期性任务执行:newScheduledThreadPool
  • 单线程化的线程池:newSingleThreadExecutor
  • 六、线程池源码
  • 线程池核心属性
  • 线程池状态变化
  • 创建线程池流程
  • 七、使用线程池异步编排任务
  • 配置线程池
  • 异步编排任务


一、多线程创建

继承Thread类

异步任务 java_异步任务 java


异步任务 java_异步任务 java_02


异步任务 java_线程池_03


异步任务 java_异步任务 java_04

实现Runnable接口

异步任务 java_单线程_05


异步任务 java_System_06


异步任务 java_多线程_07

实现Callable接口

异步任务 java_多线程_08


异步任务 java_异步任务 java_09


异步任务 java_异步任务 java_10

异步任务 java_多线程_11

二、线程优先级

异步任务 java_多线程_12


异步任务 java_System_13

三、线程同步

同步方法

异步任务 java_线程池_14


异步任务 java_多线程_15

同步代码块

异步任务 java_多线程_16

异步任务 java_线程池_17


异步任务 java_单线程_18

深入理解synchronized底层原理

深入理解synchronized底层原理,一篇文章就够了!

四、死锁

异步任务 java_System_19

五、线程池

Java通过Executors提供四种线程池,分别为:

  • newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  • newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
  • newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
    ————————————————



线程池说明

异步任务 java_单线程_20

异步任务 java_System_21


Bean方式创建异步线程池

1、配置

@Configuration
@EnableAsync
public class TaskPoolConfig {

    @Bean("taskExecutor")
    public Executor taskExecutro(){
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(10);
        taskExecutor.setMaxPoolSize(50);
        taskExecutor.setQueueCapacity(200);
        taskExecutor.setKeepAliveSeconds(60);
        taskExecutor.setThreadNamePrefix("taskExecutor--");
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.setAwaitTerminationSeconds(60);
        return taskExecutor;
    }
}

springBoot启动类的配置

在Spring Boot的主程序中配置@EnableAsync,如下所示:

@ServletComponentScan  
@SpringBootApplication  
@EnableAsync  
public class ClubApiApplication {  
    public static void main(String[] args) {  
        SpringApplication.run(ClubApiApplication.class, args);  
    }  
}

2、使用

@Component
public class AsyncTask {

    @Async("taskExecutor")
    public void tesTask(int i){
        System.out.println(Thread.currentThread().getName()+"-----"+i);
    }

    @Async("taskExecutor")
    public void stringTask(String str){
       System.out.println(Thread.currentThread().getName()+str);
    }
}

可缓存线程池:newCachedThreadPool

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。示例代码如下:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    for (int i = 0; i < 10; i++) {
        final int index = i;
    try {
        Thread.sleep(index * 1000);
    } 
        catch (InterruptedException e) {
            e.printStackTrace();
    }

	cachedThreadPool.execute(new Runnable() {
		@Override
		public void run() {
		    System.out.println(index);
		}
	});
}

线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。

定长线程池:newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:

异步任务 java_System_22


结果:

异步任务 java_异步任务 java_23

从以上结果可以看出,newFixedThreadPool的参数指定了可以运行的线程的最大数目,超过这个数目的线程加进去以后,不会运行。其次,加入线程池的线程属于托管状态,线程的运行不受加入顺序的影响。

定时及周期性任务执行:newScheduledThreadPool

创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
 scheduledThreadPool.schedule(new Runnable() {

@Override
public void run() {
    System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);

表示延迟3秒执行。

定期执行示例代码如下:

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {

@Override
public void run() {
    System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);

表示延迟1秒后每3秒执行一次。

ScheduledExecutorService比Timer更安全,功能更强大

单线程化的线程池:newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {

@Override
public void run() {
    try {
        System.out.println(index);
    Thread.sleep(2000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
        }
}
    });
}

结果依次输出,相当于顺序执行各个任务。

现行大多数GUI程序都是单线程的。Android中单线程可用于数据库操作,文件操作,应用批量安装,应用批量删除等不适合并发但可能IO阻塞性及影响UI线程响应的操作。

六、线程池源码

线程池核心属性

异步任务 java_线程池_24

线程池状态变化

异步任务 java_线程池_25

创建线程池流程

异步任务 java_异步任务 java_26

execute

异步任务 java_线程池_27


异步任务 java_多线程_28


addWorker

异步任务 java_线程池_29


异步任务 java_System_30


异步任务 java_线程池_31


异步任务 java_单线程_32


异步任务 java_单线程_33

Worker

异步任务 java_多线程_34

runWorker

异步任务 java_异步任务 java_35


异步任务 java_System_36

七、使用线程池异步编排任务

配置线程池

在配置文件配置信息

#线程池配置
my.thread.core-size=20
my.thread.max-size=200
my.thread.keep-alive-time=10

配置线程池

异步任务 java_线程池_37

@Configuration
public class MyThreadConfig {

    @Value("${my.thread.core-size}")
    private int corePoolSize;

    @Value("${my.thread.max-size}")
    private int maxPoolSize;

    @Value("${my.thread.keep-alive-time}")
    private long keepAliveTime;

    //配置线程池
    public ThreadPoolExecutor threadPoolExecutor(){
        return new ThreadPoolExecutor(corePoolSize,
                maxPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

异步编排任务

异步任务 java_单线程_38

异步任务 java_System_39

public class ThreadPool {

    public static ExecutorService executor = Executors.newFixedThreadPool(5);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future111 = CompletableFuture.supplyAsync( () -> {
            System.out.println("111");
            return null;
        },executor);

        CompletableFuture<Void> future333 = future111.thenAcceptAsync((res) -> {
            System.out.println("333");
        }, executor);

        CompletableFuture<Void> future444 = future111.thenAcceptAsync((res) -> {
            System.out.println("444");
        }, executor);

        CompletableFuture<Void> future222 = CompletableFuture.supplyAsync( () -> {
            System.out.println("222");
            return null;
        },executor);

        CompletableFuture.allOf(future333,future444,future222).get();
    }
}

异步任务 java_多线程_40