Java并发编程与高并发解决方案(一)

 

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);
    }
}

 

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值