`

java并发序列处理

阅读更多
http://www.cnblogs.com/linjiqin/archive/2013/05/30/3108188.html转载他人
并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法

在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出)。Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。

注:什么叫线程安全?这个首先要明确。线程安全就是说多线程访问同一代码,不会产生不确定的结果。

并行和并发区别

1、并行是指两者同时执行一件事,比如赛跑,两个人都在不停的往前跑;
2、并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A ,交替使用,目的是提高效率

LinkedBlockingQueue
由于LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为生产者消费者的首选,LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。

复制代码
package cn.thread;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 多线程模拟实现生产者/消费者模型
 *  
 * @author 林计钦
 * @version 1.0 2013-7-25 下午05:23:11
 */
public class BlockingQueueTest2 {
    /**
     * 
     * 定义装苹果的篮子
     * 
     */
    public class Basket {
        // 篮子,能够容纳3个苹果
        BlockingQueue<String> basket = new LinkedBlockingQueue<String>(3);

        // 生产苹果,放入篮子
        public void produce() throws InterruptedException {
            // put方法放入一个苹果,若basket满了,等到basket有位置
            basket.put("An apple");
        }

        // 消费苹果,从篮子中取走
        public String consume() throws InterruptedException {
            // take方法取出一个苹果,若basket为空,等到basket有苹果为止(获取并移除此队列的头部)
            return basket.take();
        }
    }

    // 定义苹果生产者
    class Producer implements Runnable {
        private String instance;
        private Basket basket;

        public Producer(String instance, Basket basket) {
            this.instance = instance;
            this.basket = basket;
        }

        public void run() {
            try {
                while (true) {
                    // 生产苹果
                    System.out.println("生产者准备生产苹果:" + instance);
                    basket.produce();
                    System.out.println("!生产者生产苹果完毕:" + instance);
                    // 休眠300ms
                    Thread.sleep(300);
                }
            } catch (InterruptedException ex) {
                System.out.println("Producer Interrupted");
            }
        }
    }

    // 定义苹果消费者
    class Consumer implements Runnable {
        private String instance;
        private Basket basket;

        public Consumer(String instance, Basket basket) {
            this.instance = instance;
            this.basket = basket;
        }

        public void run() {
            try {
                while (true) {
                    // 消费苹果
                    System.out.println("消费者准备消费苹果:" + instance);
                    System.out.println(basket.consume());
                    System.out.println("!消费者消费苹果完毕:" + instance);
                    // 休眠1000ms
                    Thread.sleep(1000);
                }
            } catch (InterruptedException ex) {
                System.out.println("Consumer Interrupted");
            }
        }
    }

    public static void main(String[] args) {
        BlockingQueueTest2 test = new BlockingQueueTest2();

        // 建立一个装苹果的篮子
        Basket basket = test.new Basket();

        ExecutorService service = Executors.newCachedThreadPool();
        Producer producer = test.new Producer("生产者001", basket);
        Producer producer2 = test.new Producer("生产者002", basket);
        Consumer consumer = test.new Consumer("消费者001", basket);
        service.submit(producer);
        service.submit(producer2);
        service.submit(consumer);
        // 程序运行5s后,所有任务停止
//        try {
//            Thread.sleep(1000 * 5);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        service.shutdownNow();
    }

}
复制代码
ConcurrentLinkedQueue
ConcurrentLinkedQueue是Queue的一个安全实现.Queue中元素按FIFO原则进行排序.采用CAS操作,来保证元素的一致性。
LinkedBlockingQueue是一个线程安全的阻塞队列,它实现了BlockingQueue接口,BlockingQueue接口继承自java.util.Queue接口,并在这个接口的基础上增加了take和put方法,这两个方法正是队列操作的阻塞版本。

复制代码
package cn.thread;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ConcurrentLinkedQueueTest {
    private static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
    private static int count = 2; // 线程个数
    //CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
    private static CountDownLatch latch = new CountDownLatch(count);

    public static void main(String[] args) throws InterruptedException {
        long timeStart = System.currentTimeMillis();
        ExecutorService es = Executors.newFixedThreadPool(4);
        ConcurrentLinkedQueueTest.offer();
        for (int i = 0; i < count; i++) {
            es.submit(new Poll());
        }
        latch.await(); //使得主线程(main)阻塞直到latch.countDown()为零才继续执行
        System.out.println("cost time " + (System.currentTimeMillis() - timeStart) + "ms");
        es.shutdown();
    }
    
    /**
     * 生产
     */
    public static void offer() {
        for (int i = 0; i < 100000; i++) {
            queue.offer(i);
        }
    }


    /**
     * 消费
     *  
     * @author 林计钦
     * @version 1.0 2013-7-25 下午05:32:56
     */
    static class Poll implements Runnable {
        public void run() {
            // while (queue.size()>0) {
            while (!queue.isEmpty()) {
                System.out.println(queue.poll());
            }
            latch.countDown();
        }
    }
}
复制代码
运行结果:
costtime 2360ms

改用while (queue.size()>0)后
运行结果:
cost time 46422ms

结果居然相差那么大,看了下ConcurrentLinkedQueue的API原来.size()是要遍历一遍集合的,难怪那么慢,所以尽量要避免用size而改用isEmpty().

总结了下, 在单位缺乏性能测试下,对自己的编程要求更加要严格,特别是在生产环境下更是要小心谨慎。

 

分享到:
评论

相关推荐

    JAVA并发编程实战.pdf

    根据提供的文件信息:“JAVA并发编程实战.pdf”,我们可以深入探讨与Java并发编程相关的多个核心知识点。 ### Java并发编程基础 #### 1. 并发与并行 - **并发(Concurrency)**:指一个程序中存在多个执行序列(如...

    Java Json序列化与反序列化

    总结,Java中的JSON序列化与反序列化是数据交互的重要环节,Jackson和Gson是两个常用的库,它们提供了丰富的功能和良好的API设计,使得处理JSON数据变得简单高效。通过理解和掌握这些知识,开发者可以更好地在Java...

    java通过Mysql实现类似oracle序列功能序列.rar

    在Java应用程序中,如果需要在MySQL环境中实现类似Oracle序列的功能,我们需要自己设计解决方案。以下是一些关键知识点的详细说明: 1. **Java连接MySQL**: - 首先,你需要使用JDBC(Java Database Connectivity...

    FST:快速Java序列化的替代品

    标准的Java序列化虽然方便,但在处理大量数据时,性能往往成为瓶颈。这时,FST(Fast Serialization Toolkit)作为一个高效且JDK兼容的序列化库,提供了更快的速度和更小的内存占用,成为了Java开发者的一个优秀选择...

    加快Java的文件序列化速度

    - 如果可能,利用多核处理器的优势,使用并发或并行处理来加速序列化和反序列化。 5. **预编译序列化代码**: - 使用`-Xbootclasspath/a:`参数指定自定义的`serializabilityPolicy`,可以预先生成序列化代码,...

    java并发编程1

    Java并发编程是Java开发中的核心领域,尤其在多核处理器越来越普遍的今天,理解和掌握并发编程技巧至关重要。本篇主要探讨了Java并发编程中的基本概念、优缺点、线程与进程的区别以及线程的状态转换。 首先,我们来...

    Java数字信号处理

    6. **实时处理**:Java的多线程和并发特性使得在处理实时信号流时表现优秀,可以实现实时音频、视频的捕获、处理和播放。 7. **图像处理**:Java数字信号处理也可以应用于图像领域,例如图像的灰度化、二值化、平滑...

    JAVA核心知识点整理.zip

    3. **异常处理**:Java提供了强大的异常处理机制,用于捕获和处理运行时错误。了解如何使用try-catch-finally语句块以及不同类型的异常类是必不可少的。 4. **集合框架**:Java集合框架包括接口(如List、Set、Map...

    Netty服务端与客户端依靠Java序列化传输数据

    Java序列化相对较慢,对于高并发和大数据量的场景,可能需要考虑其他的序列化库,如FST、Kryo或Google的Protobuf等。这些库提供更快的速度和更小的序列化数据大小。 7. **Netty与协议**: Netty支持多种协议,如...

    Java并发编程实践.pdf

    Java并发编程是构建高效、可扩展的多线程应用程序的关键技术。开源软件Amino,作为Apache旗下的一员,为Java并发编程提供了强大的支持。Amino设计的主要目标是提高并发操作的可操作性和伸缩性,同时保持跨平台的兼容...

    ITjava工程师序列学习列表

    除此之外,你还需要关注Java并发编程,理解线程同步、锁机制,以及并发容器如ConcurrentHashMap的使用。Java集合框架的深入理解,如ArrayList、LinkedList、HashMap等的实现原理,能帮助你更好地选择适合的数据结构...

    JAVA并发.pdf

    线程是一个独立执行的调用序列,同一个进程的线程在同一时刻共享一些系统资源(比如文件句柄等)也能访问同一个进程所创建的对象资源(内存资源)。java.lang.Thread对象负责统计和控制这种行为。 每个程序都至少...

    gsp.rar_GSP CBA数据挖掘_GSP in java_gsp java_序列模式

    例如,使用ConcurrentHashMap进行并发支持度计算,或者利用并行流(Parallel Streams)加速数据处理。 总之,GSP算法是数据挖掘序列模式领域的基石之一,它的Java实现为实际业务场景提供了强大的工具。通过理解和...

    10万字总结java面试题和答案(八股文之一)Java面试题指南

    Java序列化面试题 Java注解面试题 多线程&并发面试题 JVM面试题 Mysql面试题 Redis面试题 Memcached面试题 MongoDB面试题 Spring面试题 Spring Boot面试题 Spring Cloud面试题 RabbitMQ面试题 Dubbo 面试题 MyBatis ...

    Java 编程 源码 处理

    7. **反射机制**:Java的反射API允许在运行时动态访问类、接口、字段和方法,这对于插件化开发、序列化、动态代理等场景很有用。 8. **设计模式**:源码中常常会体现各种设计模式,如工厂模式、单例模式、观察者...

    影院管理系统(序列化)

    除了基本的序列化和反射,此项目可能还涉及到其他相关技术,如数据访问对象(DAO)模式用于与数据库交互,MVC(模型-视图-控制器)设计模式用于结构化应用程序,以及可能的多线程处理以支持并发预订操作。...

    Java序列化框架,可以任意Java对象序列化为字节数组并且完成反序列化 支持任意Java类型,序列化的对象不需要特殊接口即可

    使用说明 首先在Pom文件中引入依赖,如下 ... &lt;artifactId&gt;Fse &lt;version&gt;1.0 API 使用方式如下 Fse fse = new Fse(); TestData data = new TestData();...Fse不是并发安全的。多个线程需要使用多个实例来进行调用。

    基于java序列化的Netty编解码技术

    Netty提供了一个`SerializationCodec`类,它是`ChannelInboundHandler`和`ChannelOutboundHandler`的实现,专门用于处理Java序列化的编码和解码。在编码过程中,`SerializationCodec`会调用`ObjectOutputStream`将...

    详解java解决分布式环境中高并发环境下数据插入重复问题

    java解决分布式环境中高并发环境下数据插入重复问题 本文主要介绍了java解决分布式环境中高并发环境下数据插入重复问题的解决方案。该问题是指在高并发环境下,服务器同时接受到的重复请求,导致数据重复插入或修改...

Global site tag (gtag.js) - Google Analytics