四种线程池的创建都是重写了ThreadPoolExecutor()方法:缓存,定长,定时,单例
阿里java代码规范不允许使用Executors创建线程池,原因
1)FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
没有拒绝任务的处理方式
使用ThreadPoolExecutor创建线程池
构造方法如下:
其中ThreadFactory(创建线程的工厂)用不到,系统使用默认方式创建线程,RejectedExecutionHandler(拒绝策略)抛异常用的,一般也用不上。
corePoolSize 核心线程数(实际运行的线程数)
maximumPoolSize 最大线程数
keepAliveTime 闲置的线程最大存活时间(非核心)
keepAliveTime 当线程池中线程数量大于corePoolSize时,闲置线程最长可以存活的时间
TimeUnit时间单位
使用线程池批量提交任务:
package com.jixu.Chaoshen;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
/**
* Created by xc on 2019/1/7.
* 线程池批量提交任务
*/
public class TaskDemo implements Callable<Integer> {
private int num;
public TaskDemo() {
}
public TaskDemo(int num) {
this.num = num;
}
static ExecutorService mExecutor = new ThreadPoolExecutor(2,15,
10,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(13));
@Override
public Integer call() throws Exception {
Random r = new Random();
long time = (r.nextInt(10) + 1) * 1000;
// Thread.sleep(time);
System.out.println("耗时:" + time / 1000);
return num++;
}
public void add()throws Exception{
List<TaskDemo> list=new ArrayList<>();
for(int i=0;i<12;i++){
list.add(new TaskDemo(i));//每一个数都加一
}
List<Future<Integer>> futures = mExecutor.invokeAll(list,5000, TimeUnit.MILLISECONDS);//任务的返回
Iterator<Future<Integer>> iterator = futures.iterator();
while(iterator.hasNext()){
Future<Integer> next = iterator.next();
System.out.println(next.get());
}
mExecutor.shutdown();
}
public static void main(String[] args) {
try {
new TaskDemo().add();
} catch (Exception e) {
e.printStackTrace();
}
}
}
线程池里面创建了2个核心线程,最大线程数为15,队列为阻塞队列,设置可存储任务大小为15。任务12,
synchronized(同步锁)
public class Testsyncronized {
public static void main(String[] args) {
//开了两个线程去执行taskM任务,谁获得cup的调度谁去执行
TaskM taskM = new TaskM();
Thread thread1 = new Thread(taskM, "SyncThread1");
Thread thread2 = new Thread(taskM, "SyncThread2");//代码是错的
thread1.start();
thread2.start();
}
}
class TaskM implements Runnable{
// Object object=new Object();
int i=10;
@Override
public void run() {
while(true){
synchronized (TaskM.class){
if(i>=0){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前线程"+Thread.currentThread().getName()+",,"+i--);
}
}
}
}
}
Volatile关键字
轻量级的锁:用来确保将变量的更新操作通知到其他线程。(直接操作内存中的数据)
可以保证数据可见。
java提供了volatile来保证可见性。
当一个变量被volatile修饰后,表示着线程本地内存无效,当一个线程修改共享变量后他会立即被更新到主内存中,当其他线程读取共享变量时,它会直接从主内存中读取。当然,synchronize和锁都可以保证可见性。
java 并发编程的原子性:提供了互斥访问,同一时刻只能有一个线程对类或者方法进行操作.
深入理解java虚拟机:
所以对于对于多线程中需要及时刷新到内存的变量可以用voliate去修饰
public class TestDemo{
public static void main(String[] args) {//
ThreadDemo threadDemo = new ThreadDemo();
new Thread(threadDemo).start();
// try {
// Thread.sleep(2000);
// } catch (InterruptedException e) {//zje
// e.printStackTrace();
// }
while(true) {
// synchronized (threadDemo) {
if (threadDemo.isFlage()) {//
System.out.println("22222222");
break;
// }
}
} }
}
class ThreadDemo implements Runnable{
private volatile boolean flage=false;
public boolean isFlage() {
return flage;
}
public void setFlage(boolean flage) {
this.flage = flage;
}
@Override
public void run() {
flage=true;
// try {
// Thread.sleep(2000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
System.out.println("111111111");
}
}
至于原子性则需要通过锁或者Synchronized来解决了。