https://www.cnblogs.com/frankyou/p/10135212.html
package com.kaki.gulimall.search.thread;
import java.util.concurrent.*;
// 多线程测试不能使用 @Test 测试类 测不出效果
public class Threadtest {
/** 异步 线程池 这些感觉都是异步线程 先打印了main start main end 线程还没执行完 执行完了才
* 打印线程中的方法
* 初始化线程的四种方式
* 1)、继承 Thread
* 2)、实现 Runnable 接口
* 3)、实现 Callable 接口 + FutureTask (可以拿到返回结果,可以处理异常)
* 4)、线程池
*/
public static ExecutorService executorService = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main ....start....");
//1.继承 Thread
// Thread01 thread01 = new Thread01();
// thread01.start();
//2.实现 Runnable 接口
// Runnable01 runnable01 = new Runnable01();
// new Thread(runnable01).start();
//3. 实现 Callable 接口 + FutureTask (可以拿到返回结果,可以处理异常)
/**
* 点进 FutureTask 可以看到他接收一个 Callable01
* 而FutureTask 又实现了RunnableFuture RunnableFuture 又继承了 Runnable
* 由第二个可知 new Thread可以接收一个 Runnable
*/
// FutureTask<Integer> integerFutureTask = new FutureTask<>(new Callable01());
// new Thread(integerFutureTask).start();
// //阻塞等待线程执行完 一直要等到前面的所有异步方法执行完 获取返回结果
// Integer ires = integerFutureTask.get();
// //这个时候这一句就会在最后打印 因为他要等线程执行完获取到ires才打印
// System.out.println("main.....end....."+ires);
//一个系统一两个线程池?
//executorService.submit()
//executorService.execute(new Runnable01());
//阿里建议使用原生的方法创建线程池 不用 Executors.newFixedThreadPool(10);
/**
* 创建线程池的七大参数:
* 1.corePoolSize 核心线程数 一直保持准备就绪存活的线程数量
* 除非设置了allowCoreThreadTimeOut 那这个线程空闲了就会被回收关闭
* 2. maximumPoolSize 允许的最大线程数 控制资源
* 3. keepAliveTime 非核心线程 能够空闲的时间 (maximumPoolSize - corePoolSize)
* 超过这个时间还没有接收新任务 就释放(回收?关闭?)这个空闲线程
* 解雇临时工
* 4. unit 时间单位
* 5. BlockingQueue<Runnable> workQueue 任务的阻塞队列 如果任务有很多 线程不够了
* 就会将多余的任务放在队里里
* 只要有空闲线程 就会到队列里去取任务来执行
* 6. ThreadFactory threadFactory 线程的创建工厂
* 7. RejectedExecutionHandler handler 如果队列满了 按照我们指定的策略拒绝执行任务
*
*
*
* 运行流程:
* 1、线程池创建,准备好 core 数量的核心线程,准备接受任务
* 2、新的任务进来,用 core 准备好的空闲线程执行。
* (1) 、core 满了,就将再进来的任务放入阻塞队列中。
* 空闲的 core 就会自己去阻塞队 列获取任务执行
* (2) 、阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量
* (3) 、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime
* 指定的时间后自 动销毁。最终保持到 core 大小
* (4) 、如果线程数开到了 max 的数量,还有新任务进来,
* 就会使用 reject 指定的拒绝策 略进行处理
* 3、所有的线程创建都是由指定的 factory 创建的。
*
* 任务的阻塞队列 点进去 ctrl+h 可以看到很多实现类
* LinkedBlockingQueue<>() 默认这个队列的大小是 Integer的最大值 就是说可以放Integer的最大值那么多个任务
* 内存会不够的 需要自己指定
*
* 194集 17分钟 老师大概讲了几种拒绝策略实现类的区别 主要是 juc包下的
*
*
* 面试 :一个线程池 core 7; max 20 ,queue:50,100 并发进来怎么分配的;
* 先有 7 个能直接得到执行,接下来 50 个进入队列排队,在多开 13 个继续执行。
* 现在 70 个 被安排上了。剩下 30 个默认拒绝策略。
*
* 一般拒绝策略都是直接丢弃任务
* 如果不想抛弃任务
* 但RejectedExecutionHandler 的有一个实现类 CallerRunsPolicy
* 这个类只要线程池没关 就可以调用 Runnable 的 run方法
* Runnable 的 run方法 是一个同步方法 想要异步需要 new Thread(Runnable).start()
*/
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
200,
10,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
//常见的4种线程池
// Executors.newFixedThreadPool(); // 核心0 最大线程数Integer的最大值 所有都可以回收
// Executors.newCachedThreadPool(); //核心线程数=最大线程数 固定大小 都不可回收
//Executors.newScheduledThreadPool();// 定时任务的线程池
//Executors.newSingleThreadExecutor();// 核心线程数 和 最大线程数都是 1 后台从队列里获取任务 挨个执行
// System.out.println("main.....end.....");
}
public static class Thread01 extends Thread{
@Override
public void run() {
System.out.println("当前线程id :"+Thread.currentThread().getId());
int i = 10 /2;
System.out.println("运行结果 :"+i);
}
}
public static class Runnable01 implements Runnable{
@Override
public void run() {
System.out.println("当前线程id :"+Thread.currentThread().getId());
int i = 10 /2;
System.out.println("运行结果 :"+i);
}
}
//接口的泛型就是方法返回值的类型
public static class Callable01 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("当前线程id :"+Thread.currentThread().getId());
int i = 10 /2;
System.out.println("运行结果 :"+i);
return i;
}
}
}