精华内容
下载资源
问答
  • public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() { } public static Singleton getUniqueInstance() { //先判断对象是否已经实例过,...
  • 并发编程模式

    千次阅读 多人点赞 2019-07-31 20:12:05
    我们通过synchronized结合wait()和notify()、并发包下的锁都可以实现future模式,不过JDK已经为我们提供了future模式的实现,位于java.util.concurrent并发包下。 具体使用方法可参考文章: ...

    一、future模式

    在网上购物时,提交订单后,在收货的这段时间里无需一直在家里等候,可以先干别的事情。类推到程序设计中时,当提交请求时,期望得到答复时,如果这个答复可能很慢。传统的是一直等待到这个答复收到时再去做别的事情,但如果利用Future设计模式就无需等待答复的到来,在等待答复的过程中可以干其他事情。

    future模式核心思想就是异步调用,去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑。

    下面是时序图,左边是传统的单线程执行,右边使用了future模式。

     

    我们通过synchronized结合wait()和notify()、并发包下的锁都可以实现future模式,不过JDK已经为我们提供了future模式的实现,位于java.util.concurrent并发包下。

    具体使用方法可参考文章:https://www.2cto.com/kf/201411/351903.html

     

    二、Master-Worker模式

    Master-Worker 模式是常用的并行计算模式。它的核心思想是系统由两类进程协作工作:Master 进程和 Worker 进程。Master 负责接收和分配任务,Worker 负责处理子任务。当各个 Worker 子进程处理完成后,会将结果返回给 Master , 由 Master 进行归纳和总结。其好处是能将一个大任务分解成若干个小任务,并行执行,从而提高系统的吞吐量。

     

    在Master端往往会有如下的内容:

    1、一个盛放任务的容器,一般使用队列来保证先添加的任务先执行,因为在下面参考文章的例子中,任务在main方法中被直接一口气全部提交过来,所以worker不需要在没有任务可以取的时候而阻塞等待新任务,也就是不牵涉到阻塞,所以在这里推荐使用非阻塞的线程安全队列ConcurrentLinkedQueue性能更好,参考文章中也是使用了这种队列。

    2、一个盛放worker的线程集合,worker就是用来执行任务的,所以就是个子线程,所以可以使用HashMap<String, Thread>来盛放,key是每个worker线程的标识。

    3、一个盛放任务结果的集合,和盛放worker的线程集合不同,worker的线程集合就是在初始化Master时需要指定有多少个worker的,所以是一并初始化好的,没有并发也就没有线程安全问题,而任务结果的集合会被多个worker访问,需要线程安全的容器才行,推荐ConcurrentHashMap。

    每个worker端往往会有如下的内容:

    1、Master里盛放任务的容器的引用,因为需要获取任务。

    2、Master里盛放任务结果集合,因为需要把处理完的任务结果放进去。

    Master-Worker模式的实现可参考文章:http://blog.csdn.net/lv_fq/article/details/70853315

     

    三、生产者-消费者模式

    生产者-消费者模式是一个经典的多线程设计模式。它为多线程间的协作提供了良好的解决方案。 在生产者-消费者模式中,通常由两类线程,即若干个生产者线程和若干个消费者线程。生产者线程负责提交用户请求,消费者线程则负责具体处理生产者提交的任务。生产者和消费者之间则通过共享内存缓冲区进行通信。

     

    生产者-消费者模式可以通过线程间通信的方式实现,例如通过synchronized结合wait()和notify()、并发包下的锁都可以。但最好的方式是使用阻塞队列来实现,阻塞队列又是线程安全的这样不仅高效而且实现非常简单,将阻塞队列作为存放数据的内存缓冲区,通过调用阻塞队列的阻塞方法put()和take(),开发者不需要写困惑的wait-nofity代码去实现通信。

    生产者-消费者模式的实现可参考文章:http://blog.csdn.net/yujin753/article/details/45723175

    展开全文
  • 《死磕 Java 并发编程》系列连载中,大家可以关注一波: ????????『死磕Java并发编程系列』 01 十张图告诉你多线程那些破事 『死磕Java并发编程系列』 02 面试官:说说什么是Java内存模型? 『死磕Java并发编程...

    《死磕 Java 并发编程》系列连载中,大家可以关注一波:

    👍🏻『死磕Java并发编程系列』 01 十张图告诉你多线程那些破事

    『死磕Java并发编程系列』 02 面试官:说说什么是Java内存模型?

    『死磕Java并发编程系列』 03 面试必问的CAS原理你会了吗?

    『死磕Java并发编程系列』 04 面试官:说说Atomic原子类的实现原理?

    👍🏻『死磕Java并发编程系列』 05 图解Java中那18 把锁


    在日常编码中,Java 并发编程可是少不了,试试下面这些并发编程工具类。

    今天先带领大家一起重温学习 CountDownLatch 这个牛叉的工具类。

    认识 CountDownLatch

    CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间通信的作用(非互斥)。

    CountDownLatch 能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。

    CountDownLatch 的使用

    CountDownLatch类使用起来非常简单。

    Class 位于:java.util.concurrent.CountDownLatch

    下面简单介绍它的构造方法和常用方法。

    构造方法

    CountDownLatch只提供了一个构造方法:

    // count 为初始计数值
    public CountDownLatch(int count) {
      // ……
    }
    

    常用方法

    //常用方法1:调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
    public void await() throws InterruptedException {
      // ……
    }   
    
    // 常用方法2:和await()类似,只不过等待超时后count值还没变为0的话就会继续执行
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException { 
      // ……
    }
    
    // 常用方法3:将count值减1
    public void countDown() {
      // ……
    }  
    

    CountDownLatch 的应用场景

    我们考虑一个场景:用户购买一个商品下单成功后,我们会给用户发送各种消息提示用户『购买成功』,比如发送邮件、微信消息、短信等。所有的消息都发送成功后,我们在后台记录一条消息表示成功。

    当然我们可以使用单线程去完成,逐个完成每个操作,如下图所示:

    但是这样效率就会非常低。如何解决单线程效率低的问题?当然是通过多线程啦。

    使用多线程也会遇到一个问题,子线程消息还没发送完,主线程可能就已经打出『所有的消息都已经发送完毕啦』,这在逻辑上肯定是不对的。我们期望所有子线程发完消息主线程才会打印消息,怎么实现呢?CountDownLatch就可以解决这一类问题。

    我们使用代码实现上面的需求。

    import java.util.concurrent.*;
    
    public class OrderServiceDemo {
    
        public static void main(String[] args) throws InterruptedException {
            System.out.println("main thread: Success to place an order");
    
            int count = 3;
            CountDownLatch countDownLatch = new CountDownLatch(count);
    
            Executor executor = Executors.newFixedThreadPool(count);
            executor.execute(new MessageTask("email", countDownLatch));
            executor.execute(new MessageTask("wechat", countDownLatch));
            executor.execute(new MessageTask("sms", countDownLatch));
    
            // 主线程阻塞,等待所有子线程发完消息
            countDownLatch.await();
            // 所有子线程已经发完消息,计数器为0,主线程恢复
            System.out.println("main thread: all message has been sent");
        }
    
        static class MessageTask implements Runnable {
            private String messageName;
            private CountDownLatch countDownLatch;
    
            public MessageTask(String messageName, CountDownLatch countDownLatch) {
                this.messageName = messageName;
                this.countDownLatch = countDownLatch;
            }
    
            @Override
            public void run() {
                try {
                    // 线程发送消息
                    System.out.println("Send " + messageName);
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } finally {
                    // 发完消息计数器减 1
                    countDownLatch.countDown();
                }
            }
        }
    }
    

    程序运行结果:

    main thread: Success to place an order
    Send email
    Send wechat
    Send sms
    main thread: all message has been sent
    

    从运行结果可以看到主线程是在所有的子线程发送完消息后才打印,这符合我们的预期。

    CountDownLatch 的限制

    CountDownLatch是一次性的,计算器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,它不能再次被使用。

    大家学会了么?后面会接着讲剩余的几种并发工具类,拭目以待吧~

    我是雷小帅,爱了~

    展开全文
  • Java 并发编程

    2017-09-17 12:57:46
    Java 并发编程 Java 并发编程 Java 并发编程 Java 并发编程 Java 并发编程 Java 并发编程 Java 并发编程 Java 并发编程 Java 并发编程
  • Java并发编程

    2017-12-28 11:25:26
    Java并发编程实战,Java并发编程实战,Java并发编程实战Java并发编程实战Java并发编程实战Java并发编程实战Java并发编程实战Java并发编程实战Java并发编程实战Java并发编程实战Java并发编程实战

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 480,734
精华内容 192,293
关键字:

并发编程