`
backend-develop
  • 浏览: 25208 次
社区版块
存档分类
最新评论

Java 8并发工具包漫游指南

    博客分类:
  • Java
阅读更多

Java 8并发工具包简介

Java 8并发工具包由3个包组成,分别是java.util.concurrent、java.util.concurrent.atomic和java.util.concurrent.locks,提供了大量关于并发的接口、类、原子操作类、锁相关类。借助java.util.concurrent包,可以非常轻松地实现复杂的并发操作。java.util.concurrent包主要包含以下内容,后文将具体介绍:

阻塞队列:多种阻塞队列的实现,在队列为空或满时能够阻塞消费者或生产者相关线程。

并发容器:用于并发场景的容器类型,一般无需加锁。

线程池:创建单线程、固定大小或可缓存的线程池,支持周期性任务,也能够实现异步任务的返回。

锁:用于并发同步的锁;

原子类型:用于实现原子操作的数据类型,包括AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference等

并发工具:用于并发场景的类,可以控制并发线程的同步、等待。

 

阻塞队列BlockingQueue

在BlockingQueue中,生产者可以持续向队列插入新的元素,直到队列满为止,队列满后生产者线程被阻塞;消费者可以持续从队列取出元素,直到队列空为止,队列空后消费者线程被阻塞。

BlockingQueue提供了四种类型的操作方法,在操作不能立即执行的情况下有不同的表现。

  抛出异常 返回特殊值 阻塞 超时返回
插入 add(o) offer(o) put(o) offer(o, timeout, timeunit)
删除 remove(o) poll() take() poll(timeout, timeunit)
检查 element() peek()    

Java 8提供了多种类型的BlockingQueue实现类,

ArrayBlockingQueue:基于数组实现的有界阻塞队列,创建后不能修改队列的大小;

LinkedBlockingQueue:基于链表实现的有界阻塞队列,默认大小为Integer.MAX_VALUE,有较好的吞吐量,但可预测性差。

PriorityBlockingQueue:具有优先级的无界阻塞队列,不允许插入null,所有元素都必须可比较(即实现Comparable接口)。

SynchronousQueue:只有一个元素的同步队列。若队列中有元素插入操作将被阻塞,直到队列中的元素被其他线程取走。

DelayQueue:无界阻塞队列,每个元素都有一个延迟时间,在延迟时间之后才释放元素。

 

阻塞双端队列BlockingDueue

Dueue是“Double Ended Queue”的缩写。生产者和消费者可以在队列的两端进行插入和删除操作。

在头部提供了四种类型的操作方法,在操作不能立即执行的情况下有不同的表现。

  抛出异常 返回特殊值 阻塞 超时返回
插入 addFirst(o) offerFirst(o) putFirst(o) offerFirst(o, timeout, timeunit)
删除 removeFirst(o) pollFirst(o) takeFirst(o) pollFirst(timeout, timeunit)
检查 getFirst(o) peekFirst(o)    

在尾部提供了四种类型的操作方法,在操作不能立即执行的情况下有不同的表现。

  抛出异常 返回特殊值 阻塞 超时返回
插入 addLast(o) offerLast(o) putLast(o) offerLast(o, timeout, timeunit)
删除 removeLast(o) pollLast(o) takeLast(o) pollLast(timeout, timeunit)
检查 getLast(o) peekLast(o)    

Java 8只提供了一种类型的BlockingDueue实现类,

LinkedBlockingDeque:基于双向链表实现的有界阻塞队列,默认大小为Integer.MAX_VALUE,有较好的吞吐量,但可预测性差。

 

阻塞转移队列TransferQueue

TransferQueue接口继承了BlockingQueue接口,因此具有BlockingQueue接口的所有方法,并增加了一些方法。方法及作用如下:

tryTransfer(E e):若当前存在一个正在等待获取的消费者线程,则该方法会即刻转移e,并返回true;若不存在则返回false,但是并不会将e插入到队列中。这个方法不会阻塞当前线程,要么快速返回true,要么快速返回false。

transfer(E e):若当前存在一个正在等待获取的消费者线程,即立刻将e移交之;否则将元素e插入到队列尾部,并且当前线程进入阻塞状态,直到有消费者线程取走该元素。

tryTransfer(E e, long timeout, TimeUnit unit):若当前存在一个正在等待获取的消费者线程,会立即传输给它; 否则将元素e插入到队列尾部,并且等待被消费者线程获取消费掉。若在指定的时间内元素e无法被消费者线程获取,则返回false,同时该元素从队列中移除。

Java 8 提供了一个基于链表的实现类LinkedTransferQueue。

 

并发容器

工具包提供了队列的并发实现类ConcurrentLinkedQueue和ConcurrentLinkedDeque,两者都是无界非阻塞线程安全的队列。

ConcurrentMap接口继承了普通的Map接口,提供了线程安全和原子操作特性。Java 8 提供了实现类ConcurrentHashMap,ConcurrentHashMap不锁定整个Map,只锁定需要写入的部分,因此并发性能比HashTable要高很多。

ConcurrentNavigableMap接口继承了ConcurrentMap和NavigableMap接口,支持并发访问NavigableMap,还能让子Map具备并发访问的能力。NavigableMap是扩展的 SortedMap,具有了针对给定搜索目标返回最接近匹配项的导航方法。

Java 8 提供了实现类ConcurrentSkipListMap,并没有使用lock来保证线程的并发访问和修改,而是使用了非阻塞算法来保证并发访问,高并发时相对于TreeMap有明显的优势。

工具包提供了NavigableSet的并发实现类ConcurrentSkipListSet,是线程安全的有序集合,适用于高并发的场景,通过ConcurrentSkipListMap实现。

工具包提供了两个写时复制容器,即CopyOnWriteArrayList和CopyOnWriteArraySet。写时复制技术是一种优化策略,多个线程可以并发访问同一份数据,当有线程要修改时才进行复制然后修改。在Linux系统中,fork进程后,子进程先与父进程共享数据,需要修改时才用写时复制得到自己的副本。在Java中,写时复制容器在修改数据后,把原来容器的引用指向新容器,来实现读写分离,在并发读写中不需要加锁。写时复制容器适用于读多写少的场景,在复制时会占用较多内存,能够保证最终一致性,但无法保证瞬时一致性。

 

线程池

工具包中Executor接口定义了执行器的基本功能,即execute方法,接收Runnable对象参数并执行Runnable中的操作。

ExecutorService接口继承Executor接口后增加了关于执行器服务的定义,如关闭、立即关闭、检查关闭、等待终止、提交有返回值的任务、批量提交任务等。通过Executors的工厂方法获取ExecutorService的具体实现,目前Executors可以返回的实现类型如下:

FixedThreadPool:固定大小的线程池,创建时指定大小;

WorkStealingPool:拥有多个任务队列(以便减少连接数)的线程池;

SingleThreadExecutor:单线程执行器,顾名思义只有一个线程执行任务;

CachedThreadPool:根据需要创建线程,可以重复利用已存在的线程来执行任务;

SingleThreadScheduledExecutor:根据时间计划延迟创建单个工作线程或者周期性创建的单线程执行器;

ScheduledThreadPool:能够延后执行任务,或者按照固定的周期执行任务。

如果希望在任务执行完成后得到任务的返回值,可以调用submit方法传入Callable任务,并通过返回的Future对象查看任务执行是否完成,并获取返回值。

 

线程分叉与合并

ForkJoinPool 让我们可以很方便地把任务分裂成几个更小的任务,这些分裂出来的任务也将会提交给 ForkJoinPool。任务可以继续分割成更小的子任务,只要它还能分割。分叉和合并原理包含两个递归进行的步骤。两个步骤分别是分叉步骤和合并步骤。

一个使用了分叉和合并原理的任务可以将自己分叉(分割)为更小的子任务,这些子任务可以被并发执行。如下图所示:

通过把自己分割成多个子任务,每个子任务可以由不同的 CPU 并行执行,或者被同一个 CPU 上的不同线程执行。

只有当给的任务过大,把它分割成几个子任务才有意义。把任务分割成子任务有一定开销,因此对于小型任务,这个分割的消耗可能比每个子任务并发执行的消耗还要大。

什么时候把一个任务分割成子任务是有意义的,这个界限也称作一个阀值。这要看每个任务对有意义阀值的决定。很大程度上取决于它要做的工作的种类。

当一个任务将自己分割成若干子任务之后,该任务将等待所有子任务结束。一旦子任务执行结束,该任务可以把所有结果合并到同一个结果。图示如下:

 

使用锁实现的同步机制很像synchronized块,但是比synchronized块更灵活。锁和synchronized的主要区别在于:

Synchronized块不能保证等待进入块的线程的访问顺序;

Synchronized块无法接收参数,不能在有超时时间限制的情况下尝试访问;

Synchronized块必须包含在单个方法中,而锁的lock和unlock操作可以在单独的方法中。

工具包提供了以下几种类型的锁:

ReadWriteLock:读写锁接口,允许多个线程读取某个资源,但是一次只能有一个线程进行写操作。内部有读锁、写锁两个接口,分别保护读操作和写操作。实现类为ReentrantReadWriteLock。

ReentrantLock:可重入锁,具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大。ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥有。当锁定没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁定并返回。如果当前线程已经拥有该锁定,此方法将立即返回。内部有一个计数器,拥有锁的线程每锁定一次,计数器加1,每释放一次计数器减1。

 

原子类型

工具包提供了一些可以用原子方式进行读写的变量类型,支持无锁线程安全的单变量编程。

本质上,这些类都扩展了volatile的概念,使用一个volatile类型的变量来存储实际数据。

工具包提供了4种类型的原子变量类型:

AtomicBoolean:可原子操作的布尔对象;

AtomicInteger:可原子操作的整形对象;

AtomicLong:可原子操作的长整形对象;

AtomicReference:可原子操作的对象引用。

以AtomicInteger为例。在Java中i++和++i操作并不是线程安全的,需要加锁。AtomicInteger提供了以下几种线程安全的操作方法:

方法 定义 作用
getAndIncrement public final int getAndIncrement() i++
getAndDecrement public final int getAndDecrement() i--
incrementAndGet public final int incrementAndGet() ++i
decrementAndGet() public final int decrementAndGet() --i
getAndAdd public final int getAndAdd(int delta) 增加delta返回旧值
addAndGet public final int addAndGet(int delta) 增加delta返回新值

在此基础上,工具包还提供了原子性的数组类型,包括AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。

 

并发工具

CountDownLatch

CountDownLatch用于一个或者多个线程等待一系列指定操作的完成。初始化时,给定一个数量,每调用一次countDown() 方法数量减一。其他线程调用await方法等待时,线程会阻塞到数量减到0才开始执行。

 

CyclicBarrier 栅栏

CyclicBarrier是一种同步机制,它能够对处理一些算法的线程实现同步。换句话讲,它就是一个所有线程必须等待的一个栅栏,直到所有线程都到达这里,然后所有线程才可以继续做其他事情。在下图的流程中,线程1和线程2都到达第一个栅栏后才能够继续运行。如果线程1先到线程2后到,则线程1需要等待线程2到达栅栏处,然后两个线程才能继续运行。

 

Exchanger 交换机

Exchanger类表示一种会合点,两个线程可以在这里交换对象。两个线程各自调用exchange方法进行交换,当线程A调用Exchange对象的exchange()方法后,它会陷入阻塞状态,直到线程B也调用了exchange()方法,然后以线程安全的方式交换数据,之后线程A和B继续运行。

 

 

Semaphore 信号量

Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

 

ThreadLocalRandom产生并发随机数

使用Math.random()产生随机数,使用原子变量来保存当前的种子,这样两个线程同时调用序列时得到的是伪随机数,而不是相同数量的两倍。ThreadLocalRandom提供并发产生的随机数,能够解决多个线程发生的竞争争夺。

 

原文地址:Java 8并发工具包漫游指南

1
0
分享到:
评论

相关推荐

    42

    标题 "42" 可能是指著名的科幻小说《银河系漫游指南》中的核心概念,其中 "42" 是宇宙生命、宇宙和一切的答案。不过在这个上下文中,它似乎与 IT 和编程有关,特别是与 Kotlin 这种编程语言关联。 Kotlin 是一种...

    42moviesearch

    在描述中同样只给出了“42moviesearch”,这可能意味着该程序或服务的核心关键词是“42”和“search”,“42”通常在科幻文化中被引用为“生命、宇宙及一切问题的答案”,源自道格拉斯·亚当斯的《银河系漫游指南》...

    基于springboot的旅游景区游玩管理系统(源码+数据库)187

    基于springboot的旅游景区游玩管理系统:前端 html、jquery、bootstrap,后端 maven、springmvc、spring、jpa;角色分为管理员、用户;集成景区游玩路线、游玩攻略、在线预订等功能于一体的系统。 ## 功能介绍 ### 用户 - 基本功能:登录,注册,退出,个人信息查看与修改,密码修改 - 网站首页:主导航栏,广告图,热门酒店,热门景点 - 景区游玩路线:路线列表,按名称模糊搜索,路线详情,关注,取消关注,我的关注路线 - 景区游玩攻略:攻略列表,按名称模糊搜索,攻略详情,发布攻略,收藏攻略 - 在线预订:预订酒店,预订景点,我的预定列表,取消预定 ### 管理员 - 用户管理:用户由前台自行注册而来,管理员可以在后台查询,重置密码 - 酒店管理:酒店信息的增删改查,启用,禁用 - 景点管理:景点信息的增删改查,启用,禁用 - 审核攻略:用户在前台发布的攻略信息,管理员后台查看,并进行审核,审核通过了,其他用户才可以看到 - 路线管理:路线信息的增删改查,启用,禁用 ## 环境 - <b>IntelliJ IDEA 2021.3</b> - <b>Mysql 5.7.26</b> - <b>JDK 1.8</b>

    基于Adaline神经网络的永磁同步电机参数在线辨识方法及其优势

    内容概要:本文详细介绍了利用Adaline神经网络进行永磁同步电机参数在线辨识的方法。与传统RLS算法相比,Adaline神经网络在处理参数突变时表现出更高的稳定性和更快的响应速度。文中展示了Adaline的核心代码结构,解释了其权重更新机制,并通过具体的应用案例演示了如何将电压、电流等实时采样值作为输入,实现电阻、电感和磁链的高效辨识。此外,还讨论了Adaline在网络结构、计算复杂度以及抗噪性能等方面的优势。 适合人群:从事电机控制系统研究与开发的技术人员,尤其是对永磁同步电机参数辨识感兴趣的工程师。 使用场景及目标:适用于需要实时监测和调整永磁同步电机参数的场合,如工业自动化生产线、电动汽车等领域。主要目标是在不影响设备正常运行的情况下,提高参数辨识的精度和效率,从而优化电机控制系统的性能。 其他说明:文章强调了Adaline神经网络在处理动态系统时的独特优势,尤其是在面对参数突变时的快速响应能力和较低的计算复杂度。同时提醒使用者注意学习率的选择和输入信号的预处理,以确保最佳的辨识效果。

    【Robotics-TOOLBOX(机器人工具箱)源代码】scara机器人的gui界面:正运动学

    【Robotics_TOOLBOX(机器人工具箱)源代码】scara机器人的gui界面:正运动学

    氢汽球素材幼儿园教学课件PPT模板.pptx

    氢汽球素材幼儿园教学课件PPT模板

    网络安全Web漏洞攻击实验:从信息收集到服务器控制的详细步骤与技巧总结

    内容概要:本文档记录了一系列网络安全实验的具体过程与技术细节。实验涵盖了从简单的服务器控制到复杂的SQL注入技巧。首先介绍了通过工具如御剑扫描器和phpmyadmin进行初步的信息收集与数据库入侵,随后深入探讨了如何利用SQL注入漏洞逐步获取数据库名称、表名、列名直至最终获得敏感数据(如用户名和密码)。此外,还涉及了绕过JavaScript验证、利用文件上传漏洞等高级攻击手法。每个实验都详细描述了操作步骤、遇到的问题及解决方案,强调了实际操作中的关键点和注意事项。; 适合人群:对网络安全有兴趣的学习者,尤其是有一定编程基础并希望深入了解Web安全机制的技术人员。; 使用场景及目标:①学习常见的Web漏洞攻击方法和技术,包括SQL注入、文件上传漏洞利用等;②掌握从信息收集到最终获取目标系统控制权的完整攻击链;③提高解决实际问题的能力,培养安全意识和防护能力。; 其他说明:本内容仅用于教育目的,旨在帮助读者理解Web应用安全的重要性以及常见攻击手段的工作原理。所有实验均应在合法授权的测试环境中进行。

    基于Mamba的医学图像分割创新方案及其应用

    内容概要:本文探讨了基于Mamba的医学图像分割技术的发展现状与改进方案。首先指出传统的CNN和Transformer在医学图像分割中存在的局限性,如CNN难以捕捉长距离依赖关系,Transformer计算复杂度过高等问题。接着介绍了Mamba模型的优势,即能够在保持线性计算复杂度的同时有效捕捉长距离依赖关系。文中详细解析了上海交通大学提出的VM-UNet模型,该模型首次将Mamba结构融入UNet,通过引入视觉态空间(VSS)块和非对称编码器-解码器结构,显著提高了医学图像分割的效果。此外,文章还列举了多个基于Mamba的改进方案,如蛇形Mamba、双路架构等,并提供了具体的代码示例和技术细节。 适合人群:从事医学图像处理、计算机视觉及相关领域的研究人员和工程师。 使用场景及目标:适用于需要提高医学图像分割精度和效率的应用场景,旨在帮助研究者理解和应用最新的医学图像分割技术,推动该领域的创新发展。 其他说明:文章不仅讨论了理论和技术层面的内容,还给出了实际操作中的注意事项和优化建议,如数据预处理、损失函数的选择等,有助于读者快速上手并在实践中取得更好的效果。

    基于ssm的金港宾馆管理系统(源码+数据库)152

    基于ssm的金港宾馆管理系统:前端 jsp、jquery,后端 springmvc、spring、mybatis;角色分为管理员、用户;集成客服预定、宾馆评价、我的订单等功能于一体的系统。 ## 功能介绍 ### 用户 - 基本功能:登录,注册,退出 - 个人信息:个人信息查看与修改 - 会员中心:会员积分信息列表查询,会员商城购买商品(积分兑换商品) - 客房预订:选择入住时间和退房时间,选择房型,查询推荐房间,在线预定 - 我的订单:所有订单丨 申请取消订单丨 已取消订单丨 待付款订单丨 已支付订单丨 已入住订单丨 已完成订单 ,申请取消 - 宾馆评价:评价列表查询 - 我的评价:待审核评价丨已通过评价丨未通过评价丨我要评价 ### 管理员 - 管理员管理:管理员信息的增删改查,密码修改,超级管理员信息只能查看不允许修改 - 用户管理:用户在前台系统自行注册,管理员可以查看用户信息和修改,对会员进行升级 - 客房管理:客房信息的增删改查,修改房价,条件查询 - 订单管理:订单列表查询,入住、取消、完成操作 - 评价管理:对用户在前台的评价信息进行查询和审核 - 统计分析:根据年份和房间类型查询统计信息

    面向服务汽车诊断新架构

    面向服务汽车诊断新架构 SOVD简介

    raspberry pico rp2040 mdk例程

    raspberry pico rp2040 mdk例程

    2023-04-06-项目笔记 - 第四百七十五阶段 - 4.4.2.473全局变量的作用域-473 -2025.04-21

    2023-04-06-项目笔记-第四百七十四阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.472局变量的作用域_472- 2025-04-21

    这篇文章是一份关于Java基础面试题的汇总文档,涵盖了广泛的Java技术和相关领域的知识点

    内容概要:本文档《java基础面试汇总.pdf》涵盖了广泛的Java基础知识,包括但不限于面向对象的特征(如抽象、继承、封装、多态)、作用域规则、基本数据类型与封装类的区别、位运算与逻辑运算的区别、JVM加载类的机制、垃圾回收机制、异常处理机制、集合框架(如List、Set、Map的区别与特性)、线程的概念及其同步方法、I/O流操作、数据库连接与SQL查询、Web开发技术(如Servlet、JSP、Struts)、EJB与Spring框架的基本概念与使用、数据结构与算法(如排序算法、二叉树遍历)、C++语言特性、以及WebLogic服务器配置等。文档以问答形式呈现,针对每个知识点提供简明扼要的答案,适合用于Java开发者的面试准备和技术复习。 适合人群:具备一定编程基础,尤其是Java语言基础的学习者和开发者,包括但不限于初级到中级水平的Java程序员、Web应用开发者、企业级应用开发者等。 使用场景及目标:①作为Java开发者面试前的复习资料,帮助候选人快速回顾和掌握核心知识点;②作为日常工作中遇到具体问题时的参考手册,例如理解类加载机制、异常处理、线程同步等;③作为新手学习Java编程时的入门指南,辅助理解Java的基础概念和高级特性;④作为企业内部培训或高校教学中的辅助教材,用于指导学生或员工掌握Java技术栈的关键要素。 阅读建议:此文档内容丰富且详尽,建议读者根据自身的知识水平和技术需求有针对性地阅读。对于初学者,可以从基础概念开始逐步深入;对于有一定经验的开发者,可以重点关注自己不太熟悉或容易混淆的知识点。此外,由于文档涉及面广,建议配合实际编码练习来加深理解,尤其是对于多线程编程、异常处理、数据库操作等实践性较强的部分。

    基于ssm的二手汽车销售管理系统(源码+数据库+万字文档)107

    基于ssm的二手汽车销售管理系统:前端 jsp、jquery,后端 maven、springmvc、spring、mybatis,角色分为经理和员工;集成品牌管理、客户管理、销售管理、库存管理、收购管理等功能于一体的系统。 ## 功能介绍 - 品牌管理:品牌信息的增删改查,热门品牌列表,销量比较好的顺序排行 - 客户管理:客户资料信息的增删改查 - 销售管理:车辆销售登记,列表查询,付款 - 库存管理:车辆库存情况查询,下订单 - 收购管理:收购评估,收购订单查询 - 统计管理:财务状况(柱状图),下载excel表格 - 员工管理:员工信息的增删改查,账号激活操作 - 聊天管理:聊天内容查看,指定人员发送聊天内容 ## 环境 - <b>IntelliJ IDEA 2009.3</b> - <b>Mysql 5.7.26</b> - <b>Tomcat 7.0.73</b> - <b>JDK 1.8</b>

    FPGA实现IIC驱动:从源码到下板验证(含EEPROM模型)

    内容概要:本文详细介绍了基于FPGA实现IIC驱动的方法,涵盖IIC驱动的Verilog代码实现、状态机设计、Testbench测试平台搭建以及EEPROM模型的构建。重点讲解了IIC通信协议的关键状态及其时序控制方法,确保通信的稳定性和可靠性。同时提供了详细的代码示例,包括状态机的状态转换、时钟同步逻辑、EEPROM读写模拟等。此外,还讨论了常见的调试技巧和注意事项,如时序对齐、信号完整性、硬件约束配置等。 适合人群:具备一定FPGA开发基础的研发人员和技术爱好者。 使用场景及目标:适用于需要在FPGA平台上实现IIC通信的应用场景,如传感器数据采集、存储器读写等。目标是帮助开发者掌握IIC驱动的设计和调试方法,提高系统的稳定性和性能。 其他说明:文中提供的代码已在实际硬件环境中验证通过,建议初学者从低速开始调试,逐步提升速度。同时,针对不同的硬件环境和需求,可能需要对代码进行适当的调整和优化。

    基于ssm的摄影管理系统(源码+数据库)188

    基于ssm的摄影管理系统:前端 jsp、jquery、layui,后端 springmvc、spring、mybatis;角色分为管理员、用户;集成样片欣赏、选片指南、在线预约等功能于一体的系统。 ## 功能介绍 ### 用户 - 基本功能:登录,注册,退出,密码修改 - 网站首页:主导航栏,轮播图,宠物样片,儿童样片,个人样片,婚礼跟拍样片欣赏 - 样片欣赏:分类导航,收藏,在线预约 - 选片指南:指南信息展示,详情介绍 - 个人中心:个人资料查看与修改,我的收藏列表,我的意向列表,我的预约,我的订单 ### 管理员 - 客户管理:客户由前台自行注册而来,管理员也可以进行增删改查操作 - 收藏管理:查看客户收藏的列表信息 - 评论管理:查看客户评论信息,删除操作 - 类别管理:类别信息的增删改查 - 样片管理:样片信息的增删改查,图片上传,变更为新增,变更为可出售 - 图片管理:图片信息的增删改查 - 轮播图管理:轮播图信息的增删改查,对应前台轮播图展示 - 意向样片管理:样片信息的列表查询 - 预约管理:客户预约信息的查看,搜索,删除操作 - 订单管理:订单信息的查看与删除 - 统计分析:样片收藏率分析,订单率分析(柱状图展示) ## 环境 - <b>IntelliJ IDEA 2021.3</b> - <b>Mysql 5.7.26</b> - <b>Tomcat 7.0.73</b> - <b>JDK 1.8</b>

    secs读写器,用于半导体晶圆料盒的读取,Ti玻璃管标签

    读卡器软件支持标准工业半导体 Secs-I(Rs232)和HSMS(网口) 、 Modbus TCP /RTU协议 同时还支持欧姆龙640的 1:1 和 1:N 协议;

    零食商城.zip

    零食商城

Global site tag (gtag.js) - Google Analytics