Java multi-thread, from shallow to deep study

Shuzhou Kaige 2022-09-23 09:22:53 阅读数:830

javamulti-threadmultithreadshallow

目录

一.多线程基础
1.实现多线程的方法:
2.callableThe return value uses what is received:
3.The method used by simple threads:
4.线程的生命周期
二.线程池
1.使用工具类创建线程池-Executors
2.使用ThreadPoolExecutor创建线程池--推荐
3.Executor 和 ExecutorService 的区别
收起目录
一.多线程基础

1.实现多线程的方法:

.继承Thread类

.实现Runnable接口-重写run方法

.实现Callable接口-重写call方法

2.callableThe return value uses what is received:

.Future - 接口

.FutureTask - 类,可以new出来,传进去的callable的call方法只会执行一次.

3.The method used by simple threads:

8149bee6eae24fb7879d1ad6e421657d.png
①sleep(long millis): 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行) 

②join():指等待t线程终止.

③yield():暂停当前正在执行的线程对象,并执行其他线程.

④setPriority(): 更改线程的优先级.

.MIN_PRIORITY = 1

.NORM_PRIORITY = 5

.MAX_PRIORITY = 10

⑤interrupt():不要以为它是中断某个线程!它只是线线程发送一个中断信号,让线程在无限等待时(如死锁时) 能抛出异常,从而结束线程,但是如果你吃掉了这个异常,那么这个线程还是不会中断的!

⑥wait()

⑦.notify()

⑧.notifyall()

4.线程的生命周期

.新建,就绪,运行,阻塞,死亡.

.新建:new 就绪:start 运行:run 阻塞:sleep,阻赛io,等待通知notify

二.线程池

1.使用工具类创建线程池-Executors

//创建固定大小的线程池
//核心线程数:参数
//最大线程数:参数
//线程存活时间:0L(TimeUnit.MILLISECONDS毫秒)
//队列选择:LinkedBlockingQueue  
ExecutorService pool = Executors.newFixedThreadPool(5);

//创建缓存线程池
//核心线程数:0
//最大线程数:2147483647(Integer.MAX_VALUE)
//线程存活时间:60L(TimeUnit.SECONDS秒)
//队列选择:SynchronousQueue
ExecutorService pool = Executors.newCachedThreadPool();

//创建单个线程的线程池
//核心线程数:1
//最大线程数:1
//线程存活时间:0L(TimeUnit.MILLISECONDS毫秒)
//队列选择:LinkedBlockingQueue
ExecutorService pool = Executors.newSingleThreadExecutor();

//Create a thread pool of delayed or timed threads
//核心线程数:参数
//最大线程数:2147483647(Integer.MAX_VALUE)
//线程存活时间:0L(TimeUnit.NANOSECONDS纳秒)
//队列选择:DelayedWorkQueue
ExecutorService pool = Executors.newScheduledThreadPool(5);

//Create a thread pool of single delayed or timed threads
//核心线程数:1
//最大线程数:2147483647(Integer.MAX_VALUE)
//线程存活时间:0L(TimeUnit.NANOSECONDS纳秒)
//队列选择:DelayedWorkQueue
ExecutorService pool = Executors.newSingleThreadScheduledExecutor();

//JDK1.8
//Thread pools where creating threads is time consuming
//核心线程数:10
//最大线程数:0x7FFFFFFF = 2147483647(Integer.MAX_VALUE)最大整型数int
//线程存活时间:未发现
//队列选择:未发现
ExecutorService pool = Executors.newWorkStealingPool(10);
2.使用ThreadPoolExecutor创建线程池--推荐

//Create a thread pool of single delayed or timed threads
//核心线程数:2
//最大线程数:5
//线程存活时间:60L(TimeUnit.SECONDS秒)
//队列选择:ArrayBlockingQueue
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,5,60L, TimeUnit.SECONDS, new ArrayBlockingQueue(10));
ThreadPoolExecutor参数说明

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler) {

if (corePoolSize < 0 ||

maximumPoolSize <= 0 ||

maximumPoolSize < corePoolSize ||

keepAliveTime < 0)

throw new IllegalArgumentException();

if (workQueue == null || threadFactory == null || handler == null)

throw new NullPointerException();

this.corePoolSize = corePoolSize;

this.maximumPoolSize = maximumPoolSize;

this.workQueue = workQueue;

this.keepAliveTime = unit.toNanos(keepAliveTime);

this.threadFactory = threadFactory;

this.handler = handler;

}

.corePoolSize

核心线程数.在创建线程池之后,By default, there are no threads in the thread pool,Instead, wait for the task to arrive before creating a thread to execute the task,当线程池中的线程数目达到 corePoolSize后,New incoming tasks will be added to the cache queue,也就是那个workQueue,除非调用 ThreadPoolExecutor#prestartAllCoreThreads() 方法或者是 ThreadPoolExecutor # prestartCoreThread() 方法(From the names of these two methods, it can be seen that it means to pre-create threads,即在没有任务到来之前就创建corePoolSize个线程或一个线程).

PS:Many people do not know how much to fill in this number,Actually, you don't have to worry about it,根据实际情况填写就好,实在不知道,Just take the following values ​​according to the writing method of Ali engineer:

int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();

.maximumPoolSize

线程池中的最大线程数.表示线程池中最多可以创建多少个线程,很多人以为它的作用是这样的:”当线程池中的任务数超过 corePoolSize 后,线程池会继续创建线程,直到线程池中的线程数小于maximumPoolSize“,其实这种理解是完全错误的.它真正的作用是:当线程池中的线程数等于 corePoolSize 并且 workQueue 已满,这时就要看当前线程数是否大于 maximumPoolSize,如果小于maximumPoolSize 定义的值,则会继续创建线程去执行任务, 否则将会调用去相应的任务拒绝策略来拒绝这个任务.另外超过 corePoolSizethe thread is called"Idle Thread", This part of the thread will have a maximum idle survival time(keepAliveTime),如果超过这个空闲存活时间还没有任务被分配,This part of the thread will be recycled.

.keepAliveTime

控制"idle Thread"的空闲存活时间.这个idle ThreadExceeds mentioned above corePoolSize After those newly created threads,默认情况下,只有当线程池中的线程数大于corePoolSize,且这些"idle Thread"when not assigned a task,这个参数才会起作用.另外,如果调用了 ThreadPoolExecutor#allowCoreThreadTimeOut(boolean) 的方法,在线程池中的线程数不大于corePoolSize,且这些core Thread When not assigned tasks,keepAliveTime 参数也会起作用.

.unit

参数keepAliveTime的时间单位,共7种取值,在TimeUtil中定义:

TimeUnit.DAYS; //天

TimeUnit.HOURS; //小时

TimeUnit.MINUTES; //分钟

TimeUnit.SECONDS; //秒

TimeUnit.MILLISECONDS; //毫秒

TimeUnit.MICROSECONDS; //微妙

TimeUnit.NANOSECONDS; //纳秒

.workQueue

阻塞队列.如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,will try to add it to the queue,Note that as long as it exceeds corePoolSize The task will be added to the cache queue,The addition may or may not be successful,If successful, it will wait for an idle thread to perform the task,若添加失败(一般是队列已满),It will decide how to process the task according to the state of the current thread pool(若线程数 < maximumPoolSize 则新建线程;若线程数 >= maximumPoolSize,It will be dealt with according to the rejection policy).

常用的阻塞队列有:

1)ArrayBlockingQueue //基于数组的先进先出队列,此队列创建时必须指定大小;

2)LinkedBlockingQueue //基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;

3)synchronousQueue //这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务.

.threadFactory

线程工厂.用来为线程池创建线程,当我们不指定线程工厂时,线程池内部会调用Executors.defaultThreadFactory()创建默认的线程工厂,其后续创建的线程优先级都是Thread.NORM_PRIORITY.如果我们指定线程工厂,我们可以对产生的线程进行一定的操作.

.handler

拒绝执行策略.当线程池的缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

ThreadPoolExecutor.AbortPolicy: // 丢弃任务并抛出RejectedExecutionException异常.

ThreadPoolExecutor.DiscardPolicy: // 也是丢弃任务,但是不抛出异常.

ThreadPoolExecutor.DiscardOldestPolicy: // 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

ThreadPoolExecutor.CallerRunsPolicy: // 由调用线程处理该任务

3.Executor 和 ExecutorService 的区别

0a48e134d65b4760a113cb4197032b92.png 

版权声明:本文为[Shuzhou Kaige]所创,转载请带上原文链接,感谢。 https://javamana.com/2022/266/202209230906392799.html