Solo  当前访客:4 开始使用

CoderV的进阶笔记


Everybody wants go to heaven, but nobody wants to die.

标签: 多线程 (5)

一文搞懂四种同步工具类 有更新!

2019-09-22 09:22:57 valarchie
0  评论    0  浏览

CountDownLatch

解释:

CountDownLatch相当于一个门闩,门闩上挂了N把锁。只有N把锁都解开的话,门才会打开。怎么理解呢?我举一个赛跑比赛的例子,赛跑比赛中必须等待所有选手都准备好了,裁判才能开发令枪。选手才可以开始跑。CountDownLatch当中主要有两个方法,一个是await()会挂上锁阻塞当前线程,相当于裁判站在起始点等待,等待各位选手准备就绪,一个是countDown方法用于解锁,相当于选手准备好了之后调用countDown方法告诉裁判自己准备就绪,当所有人都准备好了之后裁判开发令枪。

代码:

public class TestCountDownLatch {
    public static void main(String[] args) {
        // 需要等待两个线程,所以传入参数为2
        CountDownLatch latch = new CountDownLatch(2);
        // 该线程运行1秒
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("1号选手准备就绪!用时1秒!");
                latch.countDown();
            }
        }).start();
        
        // 该线程运行3秒
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("2号选手准备就绪!用时3秒!");
                latch.countDown();
            }
        }).start();
        
        try {
            System.out.println("请1号选手和2号选手各就各位!");
            // 主线程在此等待两个线程执行完毕之后继续执行
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 两个线程执行完毕后,主线程恢复运行
        System.out.println("裁判发枪,1号选手和2号选手开跑!");
    }
}

同步容器和并发容器总结 有更新!

2019-09-21 15:21:26 valarchie
0  评论    0  浏览

什么是同步容器?

同步容器通过synchronized关键字修饰容器保证同一时刻内只有一个线程在使用容器,从而使得容器线程安全。synchronized的意思是同步,它体现在将多线程变为串行等待执行。(但注意一点,复合操作不能保证线程安全。举例:A线程第一步获取尾节点,第二步将尾结点的值加1,但在A线程执行完第一步的时候,B线程删除了尾节点,在A线程执行第二步的时候就会报空指针)

什么是并发容器?

并发容器指的是允许多线程同时使用容器,并且保证线程安全。而为了达到尽可能提高并发,Java并发工具包中采用了多种优化方式来提高并发容器的执行效率,核心的就是:锁、CAS(无锁)、COW(读写分离)、分段锁。

生产者消费者模式的四种实现方式 有更新!

2019-09-20 09:17:35 valarchie
0  评论    0  浏览

简述

生产者消费者模式简而言之就是两种不同的线程分别扮演生产者和消费者,通过一个商品容器来生产商品和消费商品。生产者和消费者模式是学习多线程的好例子,下文就以四种不同实现的消费者生产者模式来理解多线程的编程。

以下的例子都共用消费者和生产者对象,而将商品容器(Stock)按照四种形式进行实现。

生产者:

生产者持有商品容器,并实现了Runnable接口,在run方法中无限循环地往商品容器stock中放入商品。

public class Producer implements Runnable{
    // 商品容器
    private Stock stock;

    public Producer(Stock stock) {
        this.stock = stock;
    }

    @Override
    public void run() {

        while (true) {
            // 随机生成商品 放入商品容器 stock中
            String product = "商品" + System.currentTimeMillis() % 100;
            System.out.println("生产了" + product);
            stock.put(product);
            // 休眠0.5秒 
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }
}

FixedThreadPool vs CachedThreadPool

2019-09-17 00:17:33 valarchie
0  评论    0  浏览

之前写了一篇文章关于四种线程池的解析。
但是对于FixedThreadPool与CachedThreadPool适用的场景其实还是比较模糊难以界定的。所以笔者今天通过设计大任务并发和小任务并发来验证FixedThreadPool与CachedThreadPool的适用场景。

首先我设计了一个任务基类,它通过计算圆周率来模拟cpu的密集计算、通过写日志到本地文件来模拟IO。
这两个方法都通过参数n来调整任务的大小规模。

四种线程池的解析

2019-09-13 02:33:41 valarchie
0  评论    0  浏览

首先我们先看一下获取四种线程池的代码:

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
    ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

可以发现这四种线程池都是由Executors类生成的。依次点开四个方法的内部实现发现,它们最终调用的都是同一个ThreadPoolExecutor()的构造器,而区别在于构造器的参数不同。我们来看下ThreadPoolExecutor的参数列表:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {

正是由于这几个参数的不同导致了四种线程池的工作机制不同。参考源码对于参数的注释,我们列出参数的含义。

TOP