ExectorService 本质上是线程池
- 在于减少现场的创建销毁,节省服务器资源,做到线程服用
- 线程池刚创建时里面时空的
- 当有线程请求时,会交给核心线程处理
- 当线程池中线程达到核心线程数量时,会将新的线程放入工作队列,阻塞队列
- 工作队列满时会将线程请求,交给临时线程,临时线程处理完成后,会存活一定时间,当没有新请求时,销毁临时线程
- 核心线程,工作队列,临时线程都被占用时,新的请求会执行拒绝策略
- 创建线程池时需要考虑,核心线程数,用那种阻塞队列和队列的容量,临时线程数,拒绝策略
import java.util.concurrent.*;
public class ExectorService01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*
*int corePoolSize, 核心线程数
int maximumPoolSize, 最大线程数-核心线程数,剩余部分为临时线程
long keepAliveTime, 临时线程存活时间
TimeUnit unit, 时间单位
BlockingQueue<Runnable> workQueue 工作队列
* RejectedExecutionHandler 拒绝策略
* */
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(5);
ExecutorService executorService = new ThreadPoolExecutor(3,
5,
10,
TimeUnit.SECONDS,
workQueue,
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("拒绝执行"+r);
}
});
//执行线程 不用线程池的方法
// new Thread(new ESthread()).start();
//使用线程池执行1个线程
// executorService.execute(new ESthread());
//提交多个线程
int i;
for(i=0;i<2;i++){
executorService.execute(new ESthread());
}
//使用 submit(Callable<T>) 方式提交线程,和execute 的区别时,submit 可以有返回值
Future<String> f = executorService.submit(new SQLthread());
System.out.println(f.get());
//执行完成可以选择关闭线程池
executorService.shutdown();
}
}
/*
* 使用 实现Runnable 接口的方式创建线程
* */
class ESthread implements Runnable{
@Override
public void run() {
System.out.println("start");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("finish");
}
}
/*
* 使用实现Callable 的方式创建有返回值的线程
* 泛型来指定 返回值的类型
* */
class SQLthread implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("select");
Thread.sleep(3000);
System.out.println("done");
return "success";
}
}
预定义线程池,Executors 对 ThreadPoolExector的封装
ExecutorService es1 = Executors.newCachedThreadPool();
ExecutorService es2 = Executors.newFixedThreadPool(3);
ScheduledExecutorService ses = Executors.newScheduledThreadPool(3);
定时调度服务ScheduledThreadPoolExecutor
public class ExecutorService3 {
private static int i=0;
public static void main(String[] args) {
//定时执行
//线程池启动后达到指定时间后执行
ScheduledExecutorService es = new ScheduledThreadPoolExecutor(3);
/*
* runnable 线程
* initialDelay 推迟执行任务的时间
* period 每个多久执行一次
* timeUnit 时间单位
* */
es.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(i++);
}
},0,1,TimeUnit.SECONDS);
}
}
ForkJoinPool 合并交叉线程池,将大任务分成多个小任务
lock
- jdk1.5中提供了lock 机制,用于取代Synchronized ,传统的Synchronized使用时需要确定一个对象,如果使用错误会出现司铎
- Lock 的实现类 ReentrantLock–重入锁,如果当前的锁可以重复使用就时可重入锁,如果只能使用一次就是非重入锁
- 读写锁 ReadWriteLock
a. 读锁:允许多线程读,不允许线程写
b.写锁只允许线程写,不允许线程读 - 锁的公平和非公平策略
a. 在有限资源下线程执行的次数不均等,就称为非公平锁
b. 在公平锁策略下,通过一个执行队列,保证线程均等执行,线程不是直接抢占资源,而是先排如队列。
CountDownLatch
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
//countdownlatch 线程闭锁,当CountDownLatch 计数到 0 时执行其他线程,否则等待当前线程执行完成
/*
* 下面的例子,开启了老师和学生一共7 个线程,
* 定义 CountDownLatch =7
* 每个线程运行后 会减 1 ,当减到0 时
* 主线程 System.out.println("考试开始"); 才执行
* */
CountDownLatch cdl = new CountDownLatch(7);
new Thread(new Teacher(cdl)).start();
new Thread(new Teacher(cdl)).start();
new Thread(new Student(cdl)).start();
new Thread(new Student(cdl)).start();
new Thread(new Student(cdl)).start();
new Thread(new Student(cdl)).start();
new Thread(new Student(cdl)).start();
cdl.await();
System.out.println("考试开始");
}
}
class Teacher implements Runnable{
private CountDownLatch cdl;
public Teacher(CountDownLatch cdl) {
this.cdl = cdl;
}
@Override
public void run() {
System.out.println("老师到达现场");
cdl.countDown(); //线程执行后 计数减1
}
}
class Student implements Runnable{
private CountDownLatch cdl;
public Student(CountDownLatch cdl) {
this.cdl = cdl;
}
@Override
public void run() {
System.out.println("学生到达现场");
cdl.countDown(); //线程执行后 计数减1
}
}
Semaphore
```java
import java.util.concurrent.Semaphore;
public class SamephoreDemo {
public static void main(String[] args) {
Semaphore s = new Semaphore(6);
new Thread(new SThread(s)).start();
new Thread(new SThread(s)).start();
new Thread(new SThread(s)).start();
new Thread(new SThread(s)).start();
new Thread(new SThread(s)).start();
new Thread(new SThread(s)).start();
new Thread(new SThread(s)).start();
new Thread(new SThread(s)).start();
}
}
class SThread implements Runnable{
private Semaphore ss ;
public SThread(Semaphore ss) {
this.ss = ss;
}
@Override
public void run() {
try {
ss.acquire();
System.out.println("资源正在被使用"+Thread.currentThread().getName());
Thread.sleep(3000);
ss.release();
System.out.println("资源使用完毕"+Thread.currentThread().getName());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
### Atomic
1. Java中利用锁来保证操作原子性,在java1.8 中使用了 CAS 和 Volatile 保证属性的原子性
** CAS(compare and Swap) 比较和交换;V:当前值 A:旧值 B:预期新值 V==A?V=B:V=A ; V=B**
**Volatile 时Java中提供的一种轻量的线程同步机制,保证属性在线程之间的可见性,但不保证线程安全,禁止指令重排**