Java高并发并发导图
首先介绍连接池
1:ExecutorService是Executor直接的扩展接口,也是最常用的线程池接口,我们通常见到的线程池定时任务线程池都是它的实现类。
2:Executor的实现提供的一些方法可以返回一个 Future , 通过它我们可以跟踪到异步任务的执行和停止。
3:ExecutorService(线程池)可以被关闭来拒绝新任务。有两个不同的方法来关闭。
shutdown方法 在关闭 ExecutorService 之前等待提交的任务执行完成。
shutdownNow方法 会阻止开启新的任务并且尝试停止当前正在执行的线程,一旦调用该方法,线程池中将没有激活的任务,没有等待执行的任务,也没有新任务提交。
没有任务执行的ExecutorService将会被回收。
4:方法submit扩展了Executor.execute(Runnable) 方法, 创建并返回一个 Future 结果,这个Future可以取消任务的执行或者等待完成得到返回值。
5:方法invokeAny and invokeAll 可以执行一组任务,等待至少一个任务或者多个任务完成(ExecutorCompletionService扩展了这些方法的实现)。
以下是这个接口定义的方法:
void shutdown();
- 发起一个关闭请求,已提交的任务会执行,但不会接受新的任务请求了。 这个方法不会等待已提交的任务全部执行完成,如果你希望这样做,可以使用awaitTermination方法
List<Runnable> shutdownNow();
- 这个方法会停掉所有执行中的任务,取消等待中的任务,返回等待执行的任务 的list,方法不会等待执行中的任务停止,如果你希望这样做,可以使用awaitTermination方法
boolean isShutdown();
- 如果线程池停止完成返回true
boolean isTerminated();
- 如果线程池停止完成返回true ,当所有的任务都停止了,返回true, 注意:只有调用 shutdown 或者 shutdownNow 才返回true
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
- 调用此方法,在shutdown请求发起后,除非以下任何一种情况发生,否则当前线程将一直到阻塞。 1、所有任务执行完成 ,2、超过超时时间 ,3、当前线程被中断
<T> Future<T> submit(Callable<T> task);
- 提交一个带有返回值的任务(Callable),返回值为Future,表示了任务的执行完成结果,Future.get()方法返回成功执行后的结果。
如果你想要阻塞当前线程知道执行完成返回结果,那么你可以这样做:
result = exec.submit(aCallable).get();
<T> Future<T> submit(Runnable task, T result);
- 提交一个Runnable任务执行,返回一个Future做为任务task的代理,Future.get()方法在执行成功后可以返回结果。 Runnable task 提交的任务 ,T results 执行的结果
Future<?> submit(Runnable task);
- 提交一个Runnable任务执行,返回一个Future做为任务task的代理,Future.get()方法在执行成功后可以返回结果。
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
- 执行一组任务,返回一个Future的list,其中的Future持有任务执行完成的结果和状态 ,对于每一个返回的结果,uture.isDone = true
完成的任务可能正常结束或者异常结束,
如果在任务执行过程中参数Collection改变了,那么返回结果是不确定的。
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)
throws InterruptedException;
- 执行一组任务,返回一个Future的list,其中的Future持有任务执行完成的结果和状态 ,如果所有任务执行完成或者超时,对于每一个返回的结果中,Future.isDone = true ,当返回时,未执行完成的任务被取消,完成的任务可能正常结束或者异常结束, 如果在任务执行过程中参数Collection改变了,那么返回结果是不确定的。
<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
- 执行一组任务,当成功执行完一个任务(没有抛异常),就返回结果,不论正常返回还是异常结束,未执行的任务都会被取消。如果在任务执行过程中参数Collection改变了,那么返回结果是不确定的。
<T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
- 执行一组任务,在未超时情况下,当成功执行完一个任务(没有抛异常),就返回结果。不论正常返回还是异常结束,未执行的任务都会被取消。 如果在任务执行过程中参数Collection改变了,那么返回结果是不确定的。
Semaphore的使用(Semaphore是计数信号量)
Semaphore是计数信号量。Semaphore管理一系列许可证。每个acquire方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release方法增加一个许可证,这可能会释放一个阻塞的acquire方法。然而,其实并没有实际的许可证这个对象,Semaphore只是维持了一个可获得许可证的数量
1:线程不安全的:由于add方法不是线程安全的
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static int count = 0;
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
// 创建信号量
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
// 从信号量中获取一个允许机会
semaphore.acquire();
add();
// 释放允许,将占有的信号量归还
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count);
}
private static void add() {
count++;
}
2:线程安全的:由于AtomicInteger是线程安全的,AtomicInteger和AtomicLong都是线程安全的
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count.get());
}
private static void add() {
count.incrementAndGet();
// count.getAndIncrement();
}
3:线程安全的:由于add方法(synchronized )是线程安全的
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static int count = 0;
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count);
}
private synchronized static void add() {
count++;
}
4:线程不安全的:由于add方法是线程安全的
volatile关键字的作用是,强制变量每次都读取公共内存,这样,一旦有线程改变变量的值,其他线程马上就能发现。这就是定义里,所有线程可见的含义。
但是要注意,此关键字只能保证变量的可见性,不能保证原子性,也不会阻塞线程。也就是说多个线程并发修改变量时,还是会有并发性问题。要解决并发性的问题,还是只能用synchronized关键字。应用的场景,就是一旦改动,所有线程都能马上感知到的的情况。例如示例代码设置子线程停止循环的标志。
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static volatile int count = 0;
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count);
}
private static void add() {
count++;
// 1、count
// 2、+1
// 3、count
}
1:AtomicInteger实现线程安全
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count.get());
}
private static void add() {
count.incrementAndGet();
// count.getAndIncrement();
}
2:AtomicLong实现线程安全
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static AtomicLong count = new AtomicLong(0);
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count.get());
}
private static void add() {
count.incrementAndGet();
// count.getAndIncrement();
}
3:LongAdder实现线程安全
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static LongAdder count = new LongAdder();
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count);
}
private static void add() {
count.increment();
}
4:AtomicReference实现线程安全
是对"对象"进行原子操作
private static AtomicReference<Integer> count = new AtomicReference<>(0);
public static void main(String[] args) {
count.compareAndSet(0, 2); // 2
count.compareAndSet(0, 1); // no
count.compareAndSet(1, 3); // no
count.compareAndSet(2, 4); // 4
count.compareAndSet(3, 5); // no
log.info("count:{}", count.get());
}
5:AtomicIntegerFieldUpdater实现线程安全
private static AtomicIntegerFieldUpdater<AtomicExample5> updater =
AtomicIntegerFieldUpdater.newUpdater(AtomicExample5.class, "count");
@Getter
public volatile int count = 100;
public static void main(String[] args) {
AtomicExample5 example5 = new AtomicExample5();
if (updater.compareAndSet(example5, 100, 120)) {
log.info("update success 1, {}", example5.getCount());
}
if (updater.compareAndSet(example5, 100, 120)) {
log.info("update success 2, {}", example5.getCount());
} else {
log.info("update failed, {}", example5.getCount());
}
}
5:AtomicBoolean实现线程安全
private static AtomicBoolean isHappened = new AtomicBoolean(false);
// 请求总数
public static int clientTotal = 5000;
// 同时并发执行的线程数
public static int threadTotal = 200;
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
test();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("isHappened:{}", isHappened.get());
}
private static void test() {
if (isHappened.compareAndSet(false, true)) {
log.info("execute");
}
}
Synchronized实现线程安全
// 修饰一个代码块 作用对象:调用这个方法的对象(如果new多个就是并发执行的了)
public void test1(int j) {
synchronized (this) {
for (int i = 0; i < 10; i++) {
log.info("test1 {} - {}", j, i);
}
}
}
// 修饰一个方法 作用对象:调用这个方法的对象(同一个对象要按照顺序执行)
public synchronized void test2(int j) {
for (int i = 0; i < 10; i++) {
log.info("test2 {} - {}", j, i);
}
}
如果synchronized 修饰的方法作为父类,他的子类调用他的synchronized 方法,是不加synchronized 得
// 修饰一个类 无论多少个线程调用都是按照顺序的
public static void test1(int j) {
synchronized (SynchronizedExample2.class) {
for (int i = 0; i < 10; i++) {
log.info("test1 {} - {}", j, i);
}
}
}
// 修饰一个静态方法 无论多少个线程调用都是按照顺序的
public static synchronized void test2(int j) {
for (int i = 0; i < 10; i++) {
log.info("test2 {} - {}", j, i);
}
}