精华内容
下载资源
问答
  • 同步类容器和并发类容器

    万次阅读 多人点赞 2019-07-31 19:22:20
    什么会出现同步容器? 在Java的集合容器框架中,主要有四大类别:List、Set、Queue、Map。 注意Collection和Map是顶层接口,而List、Set、Queue接口则分别继承了Collection接口,分别代表数组、集合和队列这三大...

    一.为什么会出现同步容器?

    在Java的集合容器框架中,主要有四大类别:List、Set、Queue、Map。

    注意Collection和Map是顶层接口,而List、Set、Queue接口则分别继承了Collection接口,分别代表数组、集合和队列这三大类容器。

    像ArrayList、LinkedList都是实现了List接口,HashSet实现了Set接口,而Deque(双向队列,允许在队首、队尾进行入队和出队操作)继承了Queue接口,PriorityQueue实现了Queue接口。另外LinkedList(实际上是双向链表)同时也实现了Deque接口。

    但以上容器都是非线程安全的。如果有多个线程并发地访问这些容器时,就会出现问题。因此,在编写程序时,必须要求程序员手动地在访问到这些容器的地方进行同步处理,这样导致在使用这些容器的时候非常地不方便。所以,Java提供了同步容器供用户使用。

    二.Java中的同步类容器

    在Java中,同步容器主要包括2类:

      1)Vector、Stack、HashTable

      2)Collections类中提供的静态工厂方法创建的类

    Vector实现了List接口,Vector实际上就是一个数组,和ArrayList类似,但是Vector中的方法都是synchronized方法,即进行了同步措施;Stack也是一个同步容器,它的方法也用synchronized进行了同步,它实际上是继承于Vector类;HashTable实现了Map接口,它和HashMap很相似,但是HashTable进行了同步处理,而HashMap没有。

    Collections类是一个工具提供类,注意,它和Collection不同,Collection是一个顶层的接口。在Collections类中提供了大量的方法,比如对集合或者容器进行排序、查找等操作。最重要的是,在它里面提供了几个静态工厂方法来创建同步容器类,如下图所示:

    这些同步容器都是通过synchronized进行同步来实现线程安全的,那么很显然,这必然会影响到执行性能。

    而且虽然他们都是线程安全的,但这并不说明在任何情况下都可以线程安全,看你怎么用了,例如下面的这个例子:

    public class Test {
        static Vector<Integer> vector = new Vector<Integer>();
        public static void main(String[] args) throws InterruptedException {
            while(true) {
                for(int i=0;i<10;i++)
                    vector.add(i);
                Thread thread1 = new Thread(){
                    public void run() {
                        for(int i=0;i<vector.size();i++)
                            vector.remove(i);
                    };
                };
                Thread thread2 = new Thread(){
                    public void run() {
                        for(int i=0;i<vector.size();i++)
                            vector.get(i);
                    };
                };
                thread1.start();
                thread2.start();
                while(Thread.activeCount()>10)   {
                     
                }
            }
        }
    }

    运行结果是在执行过程中会出现数组下标越界的运行时异常。也许有朋友会问:Vector是线程安全的,为什么还会报这个错?很简单,对于Vector,虽然能保证每一个时刻只能有一个线程访问它,但是不排除这种可能,当某个线程在某个时刻执行这句时:

    for(int i=0;i<vector.size();i++)

         vector.get(i);

    假若此时vector的size方法返回的是10,i的值为9,在他要获取下标为9的元素时,有另外一个线程先执行了这句:

    for(int i=0;i<vector.size();i++)

         vector.remove(i);

    将下标为9的元素删除了,在删除过程中因为有锁,所以之前的那个线程无法执行vector.get(i);处于阻塞状态,等这个线程把下标为9的元素删除了之后获取到锁再执行。那么通过get方法访问下标为9的元素肯定就会出问题了。说明这是程序逻辑本身存在线程安全问题,因此为了保证线程安全,必须在方法调用端做额外的同步措施,如下面所示:

    public class Test {
        static Vector<Integer> vector = new Vector<Integer>();
        public static void main(String[] args) throws InterruptedException {
            while(true) {
                for(int i=0;i<10;i++)
                    vector.add(i);
                Thread thread1 = new Thread(){
                    public void run() {
                        synchronized (Test.class) {   //进行额外的同步
                            for(int i=0;i<vector.size();i++)
                                vector.remove(i);
                        }
                    };
                };
                Thread thread2 = new Thread(){
                    public void run() {
                        synchronized (Test.class) {
                            for(int i=0;i<vector.size();i++)
                                vector.get(i);
                        }
                    };
                };
                thread1.start();
                thread2.start();
                while(Thread.activeCount()>10)   {
                     
                }
            }
        }
    }

    三.Java中的并发类容器

    为了解决同步类容器的性能问题,在Java 1.5之后提供了并发容器,位于java.util.concurrent目录下,这个目录俗称并发包。

    3.1、ConcurrentMap

    ConcurrentMap接口下有两个重要的实现:ConcurrentHashMap、ConcurrentSkipListMap。ConcurrentHashMap把整个哈希表分成多个segment,每个segment一把锁,主要通过锁分段技术减小了锁的粒度,降低了冲突,从而提高了并发性。在实际的应用中,散列表一般是读多写少。ConcurrentHashMap 就针对读操作做了大量的优化,运用了很多并发技巧,如不可变对象和使用volatile保证内存可见性,这样,在大多数情况下读操作甚至无需加锁也能获得正确的值。ConcurrentHashMap的concurrencyLevel(默认值为16)表示并发级别,这个值用来确定Segment的个数,Segment的个数是大于等于concurrencyLevel的第一个2的n次方的数。比如,如果concurrencyLevel为12,13,14,15,16这些数,则Segment的数目为16(2的4次方)。理想情况下ConcurrentHashMap的真正的并发访问量能够达到concurrencyLevel,因为有concurrencyLevel个Segment,假如有concurrencyLevel个线程需要访问Map,并且需要访问的数据都恰好分别落在不同的Segment中,则这些线程能够无竞争地自由访问(因为他们不需要竞争同一把锁),达到同时访问的效果。这也是为什么这个参数起名为“并发级别”的原因。该值设置过高会照成空间的浪费,设置过低会降低并发性。这种对调优的把握是要通过对底层实现的深刻理解和不断的实践积累才能获取的。

    3.2、CopyOnWirte容器

    Cope-On-Write简称COW,是一种用于程序设计中的优化策略,称为写时复制,理解起来很简单,就是执行修改操作时进行底层数组复制,使得修改操作在新的数组上进行,不妨碍原数组的并发读操作,复制修改完成后把原数组引用指向新数组。这样做的好处是可以并发的读而不需要加锁,因为当前容器不会添加任何元素,所以也是一种读写分离的思想。但正是因为写时复制,所以不能保证数据的实时性,而只能保证最终一致性。

    在concurrent包下实现CopyOnWrite机制的容器有两种,CopyOnWriteArrayList和CopyOnWriteArraySet。

    CopyOnWriteArrayList中有一个Object数组array用来存放数据,对于set()、add()、remove()等修改数据的操作会加上重入锁ReentrantLock,等修改操作完成替换掉array的引用之后才释放锁,从而保证写操作的线程安全,而针对读操作没有任何锁。

    CopyOnWriteArraySet其实就是一个CopyOnWriteArrayList,不过就是在方法中避免重复数据而已,甚至这些避免重复数据的函数也是在CopyOnWriteArrayList中定义的,CopyOnWriteArraySet中只是包含一个CopyOnWriteArrayList的属性,然后在方法上做个包装,除了equals方法外,其他当前类中的所有函数都是调用的CopyOnWriteArrayList的方法,所以严格来讲可以使用一个CopyOnWriteArrayList作为具有Set特性的写时复制数组(不过就是没有继承AbstractSet)。

    根据CopyOnWirte容器的实现原理可知,CopyOnWirte容器保证读写分离,十分适合读多写少的场景,但不适合写多的场景。

    3.3、线程安全队列

    在并发编程中我们有时候需要使用线程安全的队列。如果我们要实现一个线程安全的队列有两种实现方式一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现,而非阻塞的实现方式则可以使用循环CAS的方式来实现。java.util.concurrent.atomic包相关类就是CAS的实现。

    ConcurrentLinkedQueue是一个适用于高并发场景下的非阻塞的队列,通过无锁的方式(采用CAS操作),实现了高并发状态下的高性能,通常ConcurrentLinkedQueue的性能优于BlockingQueue。ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素,该队列不允许NULL元素。

    阻塞队列当队列是空的时候,再想获取元素就会阻塞进入等待状态,所以非常适合生产者-消费者模式。阻塞队列BlockingQueue接口JDK提供了7种实现:

    • ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
    • LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
    • PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
    • DelayQueue:一个使用优先级队列实现的无界阻塞队列。
    • SynchronousQueue:一个不存储元素的阻塞队列。
    • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
    • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
    展开全文
  • Spring容器什么

    万次阅读 多人点赞 2018-06-14 14:13:39
    工作4年多,做了3年的java,每个项目都Spring,但对Spring一直都是知其然而不知其所以然。鄙人深知Spring是一个高深的框架,正好近期脱离加班的苦逼状态,遂决定从Spring的官方文档入手,结合Spring代码和实际项目...
    引言

    工作4年多,做了3年的java,每个项目都用Spring,但对Spring一直都是知其然而不知其所以然。鄙人深知Spring是一个高深的框架,正好近期脱离加班的苦逼状态,遂决定从Spring的官方文档入手,结合Spring代码和实际项目,全面的学习Spring,并将学习内容记录在博客上,以便以后查阅并可以和众猿讨论分享。PS:文章中会有部分是官方原句翻译,例子也会有官方例子。

    概述

    Spring容器是什么?
    Spring容器是Spring的核心,一切Spring bean都存储在Spring容器内,并由其通过IoC技术管理。Spring容器也就是一个bean工厂(BeanFactory)。应用中bean的实例化,获取,销毁等都是由这个bean工厂管理的。

    Spring容器究竟是什么。。。
    org.springframework.context.ApplicationContext接口用于完成容器的配置,初始化,管理bean。一个Spring容器就是某个实现了ApplicationContext接口的类的实例。也就是说,从代码层面,Spring容器其实就是一个ApplicationContext。

    在普通的JAVA工程中,我们可以通过代码显式new一个ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext来初始化一个Spring容器。

    在Web工程中,我们一般是通过配置web.xml的方式来初始化Spring容器。

    Spring配置文件

    Spring配置文件以XML格式呈现,如下:
    1. <?xml version=“1.0” encoding=“UTF-8”?><beans xmlns=“http://www.springframework.org/schema/beans”  
    2.        xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”  
    3.        xsi:schemaLocation=”http://www.springframework.org/schema/beans  
    4.            http://www.springframework.org/schema/beans/spring-beans.xsd”>  
    5.   
    6.   <bean id=“…” class=“…”>  
    7.     <!– collaborators and configuration for this bean go here –>  
    8.   </bean>  
    9.   
    10.   <bean id=“…” class=“…”>  
    11.     <!– collaborators and configuration for this bean go here –>  
    12.   </bean>  
    13.   
    14.   <!– more bean definitions go here –>  
    15.   
    16. </beans>  
    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
      </bean>
    
      <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
      </bean>
    
      <!-- more bean definitions go here -->
    
    </beans>
    
    
     
    在eclipse中,我们可以使用SpringSource Tool Suite工具来协助我们编写Spring的配置文件。
    工程中允许有多个Spring配置文件,我们可以按照自己的需求定义文件的分类,例如可以从处理逻辑层级来区分:services.xml,daos.xml等。

    另外,一个配置文件可以引入多个其他的配置文件,写法如下:
    1. <beans>  
    2.   
    3.     <import resource=“services.xml”/>  
    4.     <import resource=“resources/messageSource.xml”/>  
    5.     <import resource=“/resources/themeSource.xml”/>  
    6.   
    7.     <bean id=“bean1” class=“…”/>  
    8.     <bean id=“bean2” class=“…”/>  
    9.   
    10. </beans>  
    11. <strong>  
    12. <span style=“font-family:Microsoft YaHei;”></span></strong>  
    <beans>
    
        <import resource="services.xml"/>
        <import resource="resources/messageSource.xml"/>
        <import resource="/resources/themeSource.xml"/>
    
        <bean id="bean1" class="..."/>
        <bean id="bean2" class="..."/>
    
    </beans>
    <strong>
    <span style="font-family:Microsoft YaHei;"></span></strong>
     
    通过ClassPathApplicationContext初始化Spring容器

    1. ApplicationContext context =  
    2.     new ClassPathXmlApplicationContext(new String[] {“services.xml”“daos.xml”});  
    ApplicationContext context =
        new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
    
    
     
    我们写这一句简单的代码,其实Spring在里面做了很多功夫。
    首先Spring会从classpath路径下找到services.xml和daos.xml文件,
    然后将文件内的配置信息读取出来,
    然后做了N多内部的初始化工作(关于容器初始化的详细细节,后面我会补充一篇文章从源码角度详细说明)。

    我们还可以用FileSystemApplicationContext来初始化Spring容器,
    1. ApplicationContext context =  
    2.     new FileSystemXmlApplicationContext(“D:/Test/services.xml”);  
    ApplicationContext context =
        new FileSystemXmlApplicationContext("D:/Test/services.xml");
    
     
    这2中方式效果是一样的,只是通过不同的方式读取配置文件。
    容器初始完后,我们就可以用这个容器来获取我们之前配置了个bean,简单示例如下:
    1. // create and configure beans  
    2. ApplicationContext context =  
    3.     new ClassPathXmlApplicationContext(new String[] {“services.xml”“daos.xml”});  
    4.   
    5. // retrieve configured instance  
    6. PetStoreServiceImpl service = context.getBean(”petStore”, PetStoreServiceImpl.class);  
    7.   
    8. // use configured instance  
    9. List userList = service.getUsernameList();  
    10. <strong>  
    11. <span style=”font-family:Microsoft YaHei;”></span></strong>  
    // create and configure beans
    ApplicationContext context =
        new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
    
    // retrieve configured instance
    PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
    
    // use configured instance
    List userList = service.getUsernameList();
    <strong>
    <span style="font-family:Microsoft YaHei;"></span></strong>
     
    Web工程的Spring配置
    假设我们的web工程my-app的基础目录结构如下:
    my-app
    –src
    —-resources
    ——services.xml
    –WebContent
    —-META-INF
    —-WEB-INFI
    ——lib
    ——applicationContext.xml
    ——web.xml
    那么我们的web.xml需要这么,配置方式如下
    1. <context-param>  
    2.     <param-name>contextConfigLocation</param-name>  
    3.     <param-value>/WEB-INF/applicationContext.xml classpath:resources/services.xml</param-value>  
    4. </context-param>  
    5. <listener>  
    6.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    7. </listener>  
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml classpath:resources/services.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    contextConfigLocation:
    contextConfigLocation指的是Spring该去哪里读取配置文件,ContextLoaderListener用于启动的web容器(如tomcat)时,去读取配置文件并完成Spring容器的初始化(包括加载bean等)。
    关于contextConfigLocation的配置方式也是可以非常丰富的,还可以使用通配符 * ,这里简单举几个例子说明:
    1. classpath:resources/services.xml
    表示到web工程的classes/resources文件夹中查找配置文件。
    2. classpath*:resources/services.xml
    这种方式除了会到classes/resources文件夹查找,还会到lib下面的jar包中查找,查找路径是jar包内/resources/services.xml。
    3. classpath:resouces/**/*services.xml
    这种方式表示到classpath的resources文件夹下所有文件夹(不限层级,可以在第N层子文件夹中)中查找文件名以services.xml结尾的文件。
    4. 多个路径配置可以用空格分开

    classpath知识补充:
    web工程部署后,对应war包下的WEB-INF下会有一个classes文件夹和一个lib文件,当然还有其他的。
    其中classes文件夹中的内容是从工程中的源码文件夹(对应右键工程,Properties - Java Build Path - Source页签中看到的文件夹)中编译过来,lib文件夹即工程中引用的jar包。
    这个classes文件夹和lib中的jar都属于classpath。

    ContextLoaderListener:
    这个Listener就是在标准Spring Web工程中Spring开始干活的切入点,为什么要说标准?因为我们可以写一个自己的Listener去启动Spring容器。扯远了~
    因为ContextLoaderListener实现了ServletContextListener,所以在web容器启动时,ContextLoaderListener就悄悄开始工作了,至于怎么工作的还需要点篇幅去描述,这篇文件就先不细说。

    展开全文
  • 十分钟明白什么容器技术

    千次阅读 2018-07-06 14:40:51
    一、什么容器容器这个词,当你第一眼看它或许脑子里是这东西:瓶瓶罐罐、装水、装其他东西的玩意。 不管是什么,总的来说,容器给人第一印象就是——“装”。 那今天我们要说的容器技术是怎么一个概念呢?...

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

    本文由宝哥@devops运维 发表于云+社区专栏

    一、什么是容器?

    容器这个词,当你第一眼看它或许脑子里是这东西:瓶瓶罐罐、装水、装其他东西的玩意。

    img

    不管是什么,总的来说,容器给人第一印象就是——“装”。

    那今天我们要说的容器技术是怎么一个概念呢?其实,IT里的容器技术是英文单词Linux Container的直译。container这个单词有集装箱、容器的含义(主要偏集装箱意思)。不过,在中文环境下,咱们要交流要传授,如果翻译成“集装箱技术” 就有点拗口,所以结合中国人的吐字习惯和文化背景,更喜欢用容器这个词。不过,如果要形象的理解Linux Container技术的话,还是得念成集装箱会比较好。我们知道,海边码头里的集装箱是运载货物用的,它是一种按规格标准化的钢制箱子。集装箱的特色,在于其格式划一,并可以层层重叠,所以可以大量放置在特别设计的远洋轮船中(早期航运是没有集装箱概念的,那时候货物杂乱无章的放,很影响出货和运输效率)。有了集装箱,那么这就更加快捷方便的为生产商提供廉价的运输服务。

    img

    因此,IT世界里借鉴了这一理念。早期,大家都认为硬件抽象层基于hypervisor的虚拟化方式可以最大程度上提供虚拟化管理的灵活性。各种不同操作系统的虚拟机都能通过hypervisor(KVM、XEN等)来衍生、运行、销毁。然而,随着时间推移,用户发现hypervisor这种方式麻烦越来越多。为什么?因为对于hypervisor环境来说,每个虚拟机都需要运行一个完整的操作系统以及其中安装好的大量应用程序。但实际生产开发环境里,我们更关注的是自己部署的应用程序,如果每次部署发布我都得搞一个完整操作系统和附带的依赖环境,那么这让任务和性能变得很重和很低下。

    基于上述情况,人们就在想,有没有其他什么方式能让人更加的关注应用程序本身,底层多余的操作系统和环境我可以共享和复用?换句话来说,那就是我部署一个服务运行好后,我再想移植到另外一个地方,我可以不用再安装一套操作系统和依赖环境。这就像集装箱运载一样,我把货物一辆兰博基尼跑车(好比开发好的应用APP),打包放到一容器集装箱里,它通过货轮可以轻而易举的从上海码头(CentOS7.2环境)运送到纽约码头(Ubuntu14.04环境)。而且运输期间,我的兰博基尼(APP)没有受到任何的损坏(文件没有丢失),在另外一个码头卸货后,依然可以完美风骚的赛跑(启动正常)。

    img

    Linux Container容器技术的诞生(2008年)就解决了IT世界里“集装箱运输”的问题。Linux Container(简称LXC)它是一种内核轻量级的操作系统层虚拟化技术。Linux Container主要由Namespace和Cgroup两大机制来保证实现。那么Namespace和Cgroup是什么呢?刚才我们上面提到了集装箱,集装箱的作用当然是可以对货物进行打包隔离了,不让A公司的货跟B公司的货混在一起,不然卸货就分不清楚了。那么Namespace也是一样的作用,做隔离。光有隔离还没用,我们还需要对货物进行资源的管理。同样的,航运码头也有这样的管理机制:货物用什么样规格大小的集装箱,货物用多少个集装箱,货物哪些优先运走,遇到极端天气怎么暂停运输服务怎么改航道等等… 通用的,与此对应的Cgroup就负责资源管理控制作用,比如进程组使用CPU/MEM的限制,进程组的优先级控制,进程组的挂起和恢复等等。

    img

    二、容器技术的特点

    容器的特点其实我们拿跟它跟硬件抽象层虚拟化hypervisor技术对比就清楚了,我们之前也提到过,传统的虚拟化(虚拟机)技术,创建环境和部署应用都很麻烦,而且应用的移植性也很繁琐,比如你要把vmware里的虚拟机迁移到KVM里就很繁琐(需要做镜像格式的转换)。那么有了容器技术就简单了,总结下容器技术主要有三个特点:

    • \1. 极其轻量:只打包了必要的Bin/Lib;
    • \2. 秒级部署:根据镜像的不同,容器的部署大概在毫秒与秒之间(比虚拟机强很多);
    • \3. 易于移植:一次构建,随处部署;
    • \4. 弹性伸缩:Kubernetes、Swam、Mesos这类开源、方便、好使的容器管理平台有着非常强大的弹性管理能力。

    img

    三、容器的标准化

    当前,docker几乎是容器的代名词,很多人以为docker就是容器。其实,这是错误的认识,除了docker 还有coreos。所以,容器世界里并不是只有docker一家。既然不是一家就很容易出现分歧。任何技术出现都需要一个标准来规范它,不然各搞各的很容易导致技术实现的碎片化,出现大量的冲突和冗余。因此,在2015年,由Google,Docker、CoreOS、IBM、微软、红帽等厂商联合发起的OCI(Open Container Initiative)组织成立了,并于2016年4月推出了第一个开放容器标准。标准主要包括runtime运行时标准和image镜像标准。标准的推出,有助于替成长中市场带来稳定性,让企业能放心采用容器技术,用户在打包、部署应用程序后,可以自由选择不同的容器Runtime;同时,镜像打包、建立、认证、部署、命名也都能按照统一的规范来做。

    两种标准主要包含以下内容:

    1. 容器运行时标准 (runtime spec)

    a). creating:使用 create 命令创建容器,这个过程称为创建中 b). created:容器创建出来,但是还没有运行,表示镜像和配置没有错误,容器能够运行在当前平台 c). running:容器的运行状态,里面的进程处于 up 状态,正在执行用户设定的任务 d). stopped:容器运行完成,或者运行出错,或者 stop 命令之后,容器处于暂停状态。这个状态,容器还有很多信息保存在平台中,并没有完全被删除

    1. 容器镜像标准(image spec)

    a). 文件系统:以 layer 保存的文件系统,每个 layer 保存了和上层之间变化的部分,layer 应该保存哪些文件,怎么表示增加、修改和删除的文件等; b). config 文件:保存了文件系统的层级信息(每个层级的 hash 值,以及历史信息),以及容器运行时需要的一些信息(比如环境变量、工作目录、命令参数、mount 列表),指定了镜像在某个特定平台和系统的配置。比较接近我们使用 docker inspect 看到的内容; c). manifest 文件:镜像的 config 文件索引,有哪些 layer,额外的 annotation 信息,manifest 文件中保存了很多和当前平台有关的信息; d). index 文件:可选的文件,指向不同平台的 manifest 文件,这个文件能保证一个镜像可以跨平台使用,每个平台拥有不同的 manifest 文件,使用 index 作为索引。

    四、容器的主要应用场景

    容器技术的诞生其实主要解决了PAAS的层的技术实现。像OpenStack、Cloudstack这样的技术是解决IAAS层的问题。IAAS层和PAAS层大家估计也听得很多了,关于他们的区别和特性我这里不在描述。那么容器技术主要应用在哪些场景呢?目前主流的有以下几种:

    \1. 容器化传统应用 容器不仅能提高现有应用的安全性和可移植性,还能节约成本。

    每个企业的环境中都有一套较旧的应用来服务于客户或自动执行业务流程。即使是大规模的单体应用,通过容器隔离的增强安全性、以及可移植性特点,也能从 Docker 中获益,从而降低成本。一旦容器化之后,这些应用可以扩展额外的服务或者转变到微服务架构之上。

    \2. 持续集成和持续部署 (CI/CD) 通过 Docker 加速应用管道自动化和应用部署,交付速度提高至少 13 倍。

    现代化开发流程快速、持续且具备自动执行能力,最终目标是开发出更加可靠的软件。通过持续集成 (CI) 和持续部署 (CD),每次开发人员签入代码并顺利测试之后,IT 团队都能够集成新代码。作为开发运维方法的基础,CI/CD 创造了一种实时反馈回路机制,持续地传输小型迭代更改,从而加速更改,提高质量。CI 环境通常是完全自动化的,通过 git 推送命令触发测试,测试成功时自动构建新镜像,然后推送到 Docker 镜像库。通过后续的自动化和脚本,可以将新镜像的容器部署到预演环境,从而进行进一步测试。

    \3. 微服务 加速应用架构现代化进程。

    应用架构正在从采用瀑布模型开发法的单体代码库转变为独立开发和部署的松耦合服务。成千上万个这样的服务相互连接就形成了应用。Docker 允许开发人员选择最适合于每种服务的工具或技术栈,隔离服务以消除任何潜在的冲突,从而避免“地狱式的矩阵依赖”。这些容器可以独立于应用的其他服务组件,轻松地共享、部署、更新和瞬间扩展。Docker 的端到端安全功能让团队能够构建和运行最低权限的微服务模型,服务所需的资源(其他应用、涉密信息、计算资源等)会适时被创建并被访问。

    \4. IT 基础设施优化 充分利用基础设施,节省资金。

    Docker 和容器有助于优化 IT 基础设施的利用率和成本。优化不仅仅是指削减成本,还能确保在适当的时间有效地使用适当的资源。容器是一种轻量级的打包和隔离应用工作负载的方法,所以 Docker 允许在同一物理或虚拟服务器上毫不冲突地运行多项工作负载。企业可以整合数据中心,将并购而来的IT资源进行整合,从而获得向云端的可迁移性,同时减少操作系统和服务器的维护工作。

    问答

    docker和docker-compose有什么不同?

    相关阅读

    童航君:腾讯云CIS服务和clear container

    小白也能玩转Kubernetes 你与大神只差这几步

    王蕴达:腾讯云 Kubernetes 一键部署实践

    此文已由作者授权腾讯云+社区发布,原文链接:https://cloud.tencent.com/developer/article/1116709?fromSource=waitui

    欢迎大家前往腾讯云+社区或关注云加社区微信公众号(QcloudCommunity),第一时间获取更多海量技术实践干货哦~

    展开全文
  • 00 为什么要有容器? 因为数组长度是固定的,为了解决这个固定的问题,所以创建了容器容器与数组的区别? - 数组能存基础数据类型,也可以存引用数据类型;容器只能存引用数据类型 - 数组的长度是固定的,容器...

    00 为什么要有容器?

    我知道有数组,但数组有一个弊端,它是固定的,不可变。这个经常会导致出现数组越界导常的错误。并且还需要事先知道这个数组的长度才可以定义。

    但很多时候,我们并不知道未来将会发生什么,所以我们创造了容器,它是不固定的,可变的,可以根据元素的增加而增加,每次增加原数组的1.5倍。为什么是1.5倍呢,因为2倍太大了,1倍太小,所以为了保证效率,择中选1.5倍。

    数组与容器的区别?

    • 数组能存基础数据类型,也可以存引用数据类型;容器只能存引用数据类型
    • 数组的长度是固定的,容器的长度可以根据元素的增加而增加

    01 为什么会有迭代器?

    数组有的功能,容器大部分都会有。数组存放数据可能是有序的,也可能是无序的。所以容器也具备同样的功能,容器英文:Collection,有序的表示为List,即链表结构,无序的表示为Set,即想在哪建立就在哪建立。

    问题来了,有序的List,我们可以通过索引来遍历数组。但无序的Set怎么办?

    先展示一下有序的List通过size()以及get()方法来遍历数组

    public static void demo3() {
        List list = new ArrayList();
        list.add(new Student("aa",12));
        list.add(new Student("bb",13));
        list.add(new Student("cc",14));
        list.add(new Student("dd",15));
    
        for(int i = 0; i < list.size(); i++) {
            Student stu = (Student) list.get(i);
            System.out.println(stu.getName() + "," +stu.getAge());
        }
    }
    

    解决办法:分开建立两个方法不就可以了么。

    比如:List就建立一个ListIterator类(如果不考虑命名规范,这个名字可以随便定义啦),Set就再建立一个SetIterator类,我们说Java是面向对象编程,这是一种抽象编程,换句话说,就是对具体类的依赖性最小。所以,为了解决这样的问题,我们就会将这些类抽象出来,建立Iterator类,这也就是为什么会有Iterator迭代器的原因了。

    用一句话总结:Iterator类的访问方式就是把不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循环遍历集合的效果。

    为了达到抽象,我们将共同的方法给抽象出来,Iterator类就只有三个方法了,hasNext()、next()、remove()。不同的集合再由子类去重写这三种方法,而对于使用者来说,不用管是怎么实现的,直接调用就可以了。

    展开全文
  • C++容器(二):关联容器简介

    千次阅读 2015-10-01 21:06:07
    关联容器(associative container)与顺序容器的本质区别在于:关联容器通过键(Key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。虽然,关联容器的大部分行为与顺序容器相同,但其独特...
  • 什么使用IOC容器

    千次阅读 2016-06-28 21:19:30
    什么使用IOC容器  先从IOC说起,这个概念其实是从我们平常new一个对象的对立面来说的,我们平常使用对象的时候,一般都是直接使用关键字类new一个对象,那这样有什么坏处呢?其实很显然的,使用new那么就...
  • C++STL容器总结

    万次阅读 多人点赞 2019-02-27 16:34:46
    持续更新中!!! 各大容器的特点: ...1.可以下标访问的容器有(既可以插入也可以赋值):vector、deque、map; 特别要注意一下,vector和deque如果没有预先指定大小,是不能下标法插入元素的...
  • Servlet容器和Tomcat容器区别

    千次阅读 2019-07-01 15:02:34
    一提到容器,很多新手就会忘文生畏,认为这是很难很高深的东西。其实一项技术存在与发展,自然有其广度与深度的地方。但是对于开发人员而言,我们并不是要对容器研究要有多深,我们的目的有一个基本的了解,然后会...
  • 容器操作 运行容器 查看容器 停止容器 启动容器 删除容器 端口映射 容器日志 本文导读 本文承接《Docker 镜像操作 常用命令》 软件镜像(如 weChat.exe)----> 运行镜像----> 产生一个容器(正在...
  • C++ map容器和multimap容器(STL map容器

    万次阅读 多人点赞 2018-11-08 22:30:05
    1. 关联容器和map容器概述 2. map容器 2.1 map的创建以及初始化列表 2.2 map容器的一般常用属性(方法) 2.3 插入数据 2.4 数据的访问和遍历 2.5 数据的删除 2.6 map中关键词的排序 3. multimap容器 3.1 ...
  • Javavector容器排序

    千次阅读 2014-06-04 17:58:57
    Javavector容器排序 /** * 功能:定义一个Student数组,其中保存学生的基本信息,包括姓名,学号,性别,还有三门课的成绩 * 和课程对应的学分,计算出学分积,降序排序 * 时间:2014年6月4日16:33:24 * ...
  • Spring IoC容器

    千次阅读 2019-05-31 11:40:01
    核心技术 发行版5.0.8 这一部分的指导文档覆盖了所有的完全集成到Spring框架中的...Spring框架拥有他自己的AOP框架,该技术在概念上是很容器理解的,并且成功的解决了在Java企业编程中的AOP需求的80%的点。 该框...
  • Java容器有哪些?哪些是同步容器,哪些是并发容器? 一、基本概念 容器集 同步容器 并发容器 二、Collection集合接口 List接口 LinkedList类 ArrayList类 Vector类 Stack类 Set接口 HashSet类 TreeSet 三、Map集合...
  • Java容器介绍

    千次阅读 2019-07-02 09:59:14
    一、《Java编程思想》第四版容器介绍 1、不包含抽象类和遗留构件...常用的容器用黑色的粗线框表示。 点线框表示接口,实线框表示普通的(具体的)类。 带有空心箭头的点线表示一个特定的类实现了一个接口。 实心...
  • Docker技术( 容器虚拟化技术 )

    万次阅读 多人点赞 2019-10-18 19:59:21
    第一章 Docker简介诞生背景Docker 介绍虚拟机技术容器虚拟化技术官方网址第二章 Docker安装前提条件安装DockerDocker底层原理Docker结构图工作原理Docker为什么比VM快第三章 Docker常用命令帮助命令镜像命令容器命令...
  • C++容器概述和序列式容器基本操作

    千次阅读 2018-02-02 18:40:31
    容器是一些特定类型对象的集合,容器类分为序列式容器和关联容器两种。容器基本操作 容器类的一些基本操作如下图:定义和初始化 每个容器都定义了一个默认构造函数。除array之外,其他容器的默认构造函数都会创建...
  • STL容器

    千次阅读 2014-08-13 10:45:16
    1.vector vector是数组的一种类表示,它提供了自动内存管理功能,可以动态地改变vector对象的长度,并随着元素的添加和删除而增大缩小, 它提供了对元素的随机访问,在尾部添加和删除元素的时间是固定的,但在头部...
  • STL1——顺序容器和顺序容器适配器

    千次阅读 2015-08-30 14:39:45
    容器是容纳特定类型对象的集合,容器的类型分为顺序容器容器适配器和关联容器,顺序容器将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素。
  • 尽管这个解释好像并没有解释到位,但实际上,元数据对容器环境来说特别的有用。当你面对一个复杂系统的时候,假如你能获取到它的元数据的话,并对加以归类并整理,能有助于直达问题核心、更快地解决问题。
  • C++ 容器详解

    千次阅读 2018-04-14 20:35:56
    顺序容器:此处的顺序不是体现在元素的值的顺序,而是指的是元素加入容器时的位置相对应的。 关联容器:顺序容器分类: 类型 特点 vector 可变大小数组 支持快速随机访 在尾部之外的位置插入或删除元素可能...
  • Docker容器命令

    千次阅读 2019-06-12 11:48:05
    Docker容器命令 文章目录Docker容器命令1. docker运行(创建)容器命令2. docker查看容器命令3. docker退出容器命令4. docker启动容器命令5. docker重启容器命令6. docker停止容器命令7. docker删除容器命令8. docker...
  • 什么是Spring IoC容器

    千次阅读 2020-06-09 22:24:29
    图例说明一下,传统程序设计如下,都是主动去创建相关对象然后再组合起来: 当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如下图所示: 4 IoC能做什么 IoC 不是一种技术,只是一种思想,一个重要...
  • Docker总结(配合阿里云容器镜像服务)

    万次阅读 多人点赞 2019-04-09 16:34:40
    Docker是个很好的工具,刚开始觉得还没虚拟环境好用,随着深入了解,越发觉得Docker好用,今天就来总结一下使用心得。 一、Docker基础 1、背景知识 1)docker是什么? Docker 属于 Linux 容器的一种封装,...
  • C++容器(顺序容器、关联容器

    千次阅读 2012-04-05 20:18:12
    转载:http://hi.baidu.com/36470902/blog/item/50ed5a8b21491f1bc9fc7a3b.html ... 容器主要分为顺序容器和关联容器。 一,顺序容器 vector--连续存储的元素,单向的 list----由节点组
  • 关联容器

    千次阅读 2007-05-22 16:04:00
    关联容器
  • docker容器启动参数

    千次阅读 2018-09-19 19:31:00
    docker run [option] 镜像名 [向启动容器中传入的命令] 常用可选参数说明: ...-v 表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录,即 宿主机目录:容器中目录),可以使 多个-v 做...
  • 同步容器与并发容器类简介

    千次阅读 2018-09-02 11:03:56
    同步容器类   同步容器类包括Vector和HashTable,二者都是早期JDK的一部分,此外还包括在JDK1.2当中添加的一些功能相似的类,这些同步的封装类是由Collections.synchronizedXxx等工厂方法创建的。这些类实现线程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 550,642
精华内容 220,256
关键字:

容器用什么表示