java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类
1.corePoolSize: 核心池的大小,默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去
执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
2.maximumPoolSize : 线程池最大线程数,它表示在线程池中最多能创建多少个线程;
3.keepAliveTime : 表示线程没有任务执行时最多保持多久时间会终止.默认情况下,只有当线程池中的线程数大于
corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize时,如果一个线程
空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了
allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime
参数也会起作用,直到线程池中的线程数为0;
4.unit : 参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:
TimeUnit.DAYS; //天
TimeUnit.HOURS; //小时
TimeUnit.MINUTES; //分钟
TimeUnit.SECONDS; //秒
TimeUnit.MILLISECONDS; //毫秒
TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS; //纳秒
5.workQueue : 一个阻塞队列,用来存储等待执行的任务
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;
ArrayBlockingQueue和PriorityBlockingQueue使用较少,
一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
6.threadFactory : 线程工厂,主要用来创建线程;
7.handler : 表示当拒绝处理任务时的策略,
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
在ThreadPoolExecutor类中有几个非常重要的方法:
execute() : 方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,
这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,
交由线程池去执行。
submit() : 方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,
在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,
但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,
会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果
shutdown()和shutdownNow()是用来关闭线程池的。
二.深入剖析线程池实现原理
1.线程池状态
runState表示当前线程池的状态,它是一个volatile变量用来保证线程之间的可见性;
当创建线程池后,初始时,线程池处于RUNNING状态;
如果调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不能够接受新的任务,它会等待所有任务执行完毕;
如果调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务;
当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态
以上内容:
https://www.cnblogs.com/dolphin0520/p/3932921.html
Java并发编程:Callable、Future和FutureTask
Callable接口可以看作是Runnable接口的补充,call方法带有返回值,并且可以抛出异常。
把Callable实例当作参数,生成一个FutureTask的对象,然后把这个对象当作一个Runnable,作为参数另起线程。
Future的核心思想是:一个方法f,计算过程可能非常耗时,等待f返回,显然不明智。可以在调用f的时候,立马返回一个Future,可以通过Future这个数据结构去控制方法f的计算过程。
这里的控制包括:
get方法:获取计算结果(如果还没计算完,也是必须等待的)
cancel方法:还没计算完,可以取消计算过程
isDone方法:判断是否计算完
isCancelled方法:判断计算是否被取消
https://www.cnblogs.com/dolphin0520/p/3949310.html
1.1.1、实现原理
方式1:自定义类继承Thread类,重写run方法,调用start启动线程,会自动调用我们线程类中的run方法。
方式2:自定义类,实现Runnable接口,把任务对象传给Thread对象。调用Thread对象的start方法,执行Thread的run
总结多线程的安全问题发生的原因:
1、 首先必须有多线程。
2、 多个线程在操作共享的数据,并且对共享数据有修改。
3、 本质原因是CPU在处理多个线程的时候,在操作共享数据的多条代码之间进行切换导致的。
Java线程池
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
1.使用Callable+Future获取执行结果
public class Test {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
Task task = new Task();
Future<Integer> result = executor.submit(task);
executor.shutdown();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("主线程在执行任务");
try {
System.out.println("task运行结果"+result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("所有任务执行完毕");
}
}
class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("子线程在进行计算");
Thread.sleep(3000);
int sum = 0;
for(int i=0;i<100;i++)
sum += i;
return sum;
}
}
2.使用Callable+FutureTask获取执行结果
public class Test {
public static void main(String[] args) {
//第一种方式
ExecutorService executor = Executors.newCachedThreadPool();
Task task = new Task();
FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
executor.submit(futureTask);
executor.shutdown();
//第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread
/*Task task = new Task();
FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
Thread thread = new Thread(futureTask);
thread.start();*/
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("主线程在执行任务");
try {
System.out.println("task运行结果"+futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("所有任务执行完毕");
}
}
class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("子线程在进行计算");
Thread.sleep(3000);
int sum = 0;
for(int i=0;i<100;i++)
sum += i;
return sum;
}
}
https://blog.youkuaiyun.com/doutao6677/article/details/55509719