当前位置: 首页 > news >正文 网站建设 天猫 保证金北白象镇做公司网站哪里有 news 2025/11/5 17:14:16 网站建设 天猫 保证金,北白象镇做公司网站哪里有,浙江seo关键词,迷你主机做网站注#xff1a;本笔记是阅读《Java高并发核心编程卷2》整理的笔记#xff01; 导致并发修改的原因 基本概念 synchronized 关键字 方法声明synchronized synchronized 同步块 消费者生产者问题 Java对象结构与内置锁 四种内置锁 偏向锁原理 偏向锁的撤销 偏向锁的膨胀 全局安全…注本笔记是阅读《Java高并发核心编程卷2》整理的笔记 导致并发修改的原因 基本概念 synchronized 关键字 方法声明synchronized synchronized 同步块 消费者生产者问题 Java对象结构与内置锁 四种内置锁 偏向锁原理 偏向锁的撤销 偏向锁的膨胀 全局安全点(非重点记住结论即可) 轻量级锁的原理 轻量级锁的膨胀 重量级锁原理 synchronized的执行过程 线程间的通信 导致并发修改的原因 例如Java中的i等指令并非是原子操作而是三条指令的集合“内存取值”、“寄存器增加1”、“存值到内存” 。 因此如果是多线程并发使用CPU当某个线程正在计算时被抢夺了CPU然后恰好被另外一个线程修改了变量将发生覆盖。根本原因是CPU上下文切换导致指令交错执行 getstatic i // 获取静态变量i的值 iconst_1 // 准备常量1 iadd // 自增 putstatic i // 将修改后的值存入静态变量i基本概念 临界资源一次仅允许一个进程使用的资源成为临界资源一旦临界区资源被占用想使用该资源的其他线程则必须等待。 临界区访问临界资源的代码块。线程进入临界区代码段之前必须在进入区申请资源申请成功之后进行临界区代码段执行完成之后释放资源。临界区代码段的进入和退出具体如图2-1所示。 竞态条件多个线程没有互斥访问临界区并发在临界区内执行由于代码的执行序列不同而导致结果无法预测称之为发生了竞态条件。 为了避免竞态条件的问题我们必须保证临界区代码段操作必须具备排他性 。一个线程进入Critical Section执行时其他线程不能进入临界区代码段执行。 synchronized 关键字 每个Java对象都隐含有一把锁这里称为Java内置锁|对象锁 。使用synchronizedsyncObject调用相当于获取syncObject的内置锁所以可以使用内置锁对临界区代码段进行排他性保护。 方法声明synchronized static int amount 0; public synchronized void selfPlus() {amount; }在方法声明中设置synchronized同步关键字保证了其方法的代码执行流程是排他性的。任何时间只允许一条线程进入同步方法临界区代码段如果其他线程都需要执行同一个方法那么只能等待和排队。 使用this对象锁作为进入临界区的同步锁 。也就是说方法上声明synchronized 锁是当前对象。 synchronized 同步块 为了提升吞吐量可以将synchronized关键字放在函数体内同步一个代码块。 synchronized同步块的写法是 synchronized(syncObject) //同步块而不是方法 {//临界区代码段的代码块 }synchronized同步块后边的括号中是一个syncObject对象代表着进入临界区代码段需要获取syncObject对象的监视锁或者说将syncObject对象监视锁作为临界区代码段的同步锁。由于每一个Java对象都有一把监视锁 Monitor因此任何Java对象都能作为synchronized的同步锁。 synchronized代码块比synchronized方法更加细粒度地控制了多条线程的同步访问 。同步锁需要手动给定 syncObject 。如果某个synchronized方法是static静态方法synchronized的同步锁并不是普通Object对象的监视锁而是类所对应的Class对象的监视锁。 通过synchronized关键字所抢占的同步锁什么时候释放呢一种场景是synchronized块代码块或者方法正确执行完毕监视锁自动释放另一种场景是程序出现异常非正常退出synchronized块监视锁也会自动释放。所以使用synchronized块时不必担心监视锁的释放问题。 消费者生产者问题 生产者―消费者问题关键是 1保证生产者不会在缓冲区满时加入数据消费者也不会在缓冲区中为空时消耗数据。 2保证在生产者加入过程、消费者消耗过程中不会产生错误的数据和行为。 这里需要保证两个地方的互斥访问一个是缓冲区一个是记录缓存区的变量count。但是粗暴的使用对象锁作为同步锁这样一来所有的生产、消费动作在执行过程中都需要抢占同一个同步锁最终的结果是所有的生产、消费动作都被串行化了导致效率低下。如何开发出并行化程度更高的生产者消费者模式实现版本 后续就是围绕这个问题来讲解的先从基础知识开始讲的。 Java 对象结构与内置锁 Java内置锁的很多重要信息都存放在对象结构中 不同的JVM的对象结构的实现不一样这里以HotSpot JVM为例。 Java对象 Object实例结构包括三部分对象头、对象体和对齐字节。 对象头包括三个字段第一个字段叫作Mark Word标记字用于存储自身运行时的数据例如GC标志位、哈希码、锁状态等信息。 Mark Word标记字字段主要用来表示对象的线程锁状态另外还可以用来配合GC、存放该对象的hashCode。 Mark Word的位长度为JVM的一个Word大小也就是说32位JVM的Mark Word为32位 64位JVM的Mark Word为64位。 Java内置锁的状态总共有4种级别由低到高依次为无锁、偏向锁、轻量级锁和重量级锁。其实在JDK 1.6之前 Java内置锁还是一个重量级锁是一个效率比较低下的锁在JDK 1.6之后 JVM为了提高锁的获取与释放效率对synchronized的实现进行了优化引入了偏向锁、轻量级锁的实现从此以后Java内置锁的状态就有了4种无锁、偏向锁、轻量级锁和重量级锁并且4种状态会随着竞争的情况逐渐升级而且是不可逆的过程即不可降级也就是说只能进行锁升级从低级别到高级别。 4位的Java对象分代年龄。在GC中如果对象在Survivor区复制一次年龄增加1。当对象达到设定的阈值时将会晋升到老年代。默认情况下并行GC的年龄阈值为15并发GC的年龄阈值为6。由于age只有4位因此最大值为15这就是-XX:MaxTenuringThreshold选项最大值为15的原因。identity_hashcode 31位的对象标识HashCode哈希码采用延迟加载技术当调用Object.hashCode()方法计算对象的HashCode后其结果将被写到该对象头中。thread 54位的线程ID值为持有偏向锁的线程ID。lock锁状态标记位占两个二进制位。biased_lock对象是否启用偏向锁标记只占1个二进制位。为1时表示对象启用偏向锁为0时表示对象没有偏向锁。 四种内置锁 在JDK 1.6版本之前所有的Java内置锁都是重量级锁。重量级锁会造成CPU在用户态和核心态之间频繁切换所以代价高、效率低。 JDK 1.6版本为了减少获得锁和释放锁所带来的性能消耗引入了“偏向锁”和“轻量级锁”实现。所以在JDK 1.6版本里内置锁一共有4种状态无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态这些状态随着竞争情况逐渐升级。内置锁可以升级但不能降级意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种能升级却不能降级的策略其目的是为了提高获得锁和释放锁的效率。 无锁状态 Java对象未加锁状态就是无锁状态例如对象刚刚创建偏向锁标识位是0、锁状态01 。 偏向锁状态 偏向锁是指一段同步代码一直被同一个线程所访问那么该线程会自动获取锁降低获取锁的代价。如果内置锁处于偏向状态当有一个线程来竞争锁时先用偏向锁表示内置锁偏爱这个线程这个线程要执行该锁关联的同步代码时不需要再做任何检查和切换。偏向锁在竞争不激烈的情况下效率非常高。偏向锁状态的Mark Word会记录内置锁自己偏爱的线程ID如下内置锁会将该线程当作自己的熟人。 轻量级锁状态 当有两个线程开始竞争这个锁对象时情况发生变化了不再是偏向独占锁了锁会升级为轻量级锁两个线程公平竞争哪个线程先占有锁对象锁对象的Mark Word就指向哪个线程的栈帧中的锁记录。 当锁处于偏向锁又被另一个线程所企图抢占时偏向锁就会升级为轻量级锁。企图抢占的线程会通过自旋的形式尝试获取锁不会阻塞抢锁线程以便提高性能。 自旋原理非常简单如果持有锁的线程能在很短时间内释放锁资源那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态它们只需要等一等自旋等持有锁的线程释放锁后即可立即获取锁这样就避免用户线程和内核切换的消耗。但是线程自旋是需要消耗 CPU的如果一直获取不到锁那线程也不能一直占用CPU自旋做无用功所以需要设定一个自旋等待的最大时间。JDK 1.6之后引入了适应性自旋锁适应性自旋锁意味着自旋的时间不是固定的而是由前一次在同一个锁上的自旋时间以及锁的拥有者的状态来决定的。线程如果自旋成功了下次自旋的次数就会更多如果自旋失败了自旋的次数就会减少。如果持有锁的线程执行的时间超过自旋等待的最大时间仍没有释放锁就会导致其他争用锁的线程在最大等待时间内还是获取不到锁自旋不会一直持续下去这时争用线程会停止自旋进入阻塞状态该锁膨胀为重量级锁。 重量级锁状态 重量级锁会让其他申请的线程之间进入阻塞性能降低。重量级锁也就叫同步锁这个锁对象Mark Word再次发生变化会指向一个监视器对象该监视器对象用集合的形式来登记和管理排队的线程。 偏向锁原理 偏向锁主要解决无竞争下的锁性能问题所谓的偏向就是偏心即锁会偏向于当前已经占有锁的线程。 在实际场景中如果一个同步块或方法没有多个线程竞争而且总是由同一个线程多次重入获取锁如果每次还有阻塞线程唤醒CPU从用户态转核心态那么对于CPU是一种资源的浪费为了解决这类问题就引入了偏向锁的概念。 偏向锁的核心原理是如果不存在线程竞争的一个线程获得了锁那么锁就进入偏向状态此时Mark Word的结构变为偏向锁结构 然后线程的ID记录在锁对象的Mark Word中使用CAS操作完成。 以后该线程获取锁的时候判断一下线程ID和标志位就可以直接进入同步块连CAS操作都不需要这样就省去了大量有关锁申请的操作从而也就提升了程序的性能。 在大多数情况下锁不仅不存在多线程竞争而且总是由同一线程多次获得锁因此在大多数情况下偏向锁是能提升性能的。 如果是同一个线程多次获得锁如果不是偏向锁将会导致无限制的获取锁、释放锁操作这将导致无竞争情况下的系统底层的同步操作性能很低。如果使用偏向锁之前获得锁的线程再次获得锁时会判断偏向锁的线程ID是否指向自己。如果指向自己拿锁成功。如果未指向当前线程当前线程会采用CAS操作将Mark Word中线程ID设置为当前线程ID如果CAS操作成功那么获取偏向锁成功去执行同步代码块如果CAS操作失败那么表示有竞争抢锁线程被挂起撤销占锁线程的偏向锁然后将偏向锁膨胀为轻量级锁。 偏向锁的缺点如果锁对象时常被多条线程竞争偏向锁就是多余的并且其撤销的过程会带来一些性能开销。 偏向锁的撤销 假如有多个线程来竞争偏向锁此对象锁已经有所偏向其他的线程发现偏向锁并不是偏向自己就说明存在了竞争尝试撤销偏向锁很可能引入安全点然后膨胀到轻量级锁。 以下两个操作导致撤销偏向锁 1多个线程竞争偏向锁。 2调用偏向锁对象obj.的obj.hashCode()方法计算对象的哈希码之后偏向锁将被撤销。因为对象头的Mark Word只有64位然而54位被线程ID占用了因此没有存放HashCode。所以只能撤销偏向锁将Mark Word用于存放对象的哈希码。轻量级锁会在帧栈的Lock Record锁记录中记录哈希码重量级锁会在监视器中记录哈希码起到了对哈希码备份的作用。而偏向锁没有地方备份哈希码。 偏向锁的膨胀 如果偏向锁被占据一旦有第二个线程争抢这个对象因为偏向锁不会主动释放所以第二个线程可以看到内置锁偏向状态这时表明在这个对象锁上已经存在竞争了。 JVM检查原来持有该对象锁的占有线程是否依然存活如果挂了就可以将对象变为无锁状态然后进行重新偏向偏向为抢锁线程。如果JVM检查到原来的线程依然存活就表明原来的线程还在使用偏执锁发生锁竞争撤销原来的偏向锁将偏向锁膨胀INFLATING为轻量级锁。经验表明其实大部分情况下进入一个同步代码块的线程都会是同一个线程。这也是为什么JDK会引入偏向锁出现的原因。所以总体来说使用偏向锁带来的好处还是大于偏向锁撤销和膨胀的所带来的代价。 全局安全点非重点记住结论即可 JVM包含了一些虚拟机后台线程包含VMThread、 GC线程、系统接收外部请求的线程等以及用户定义线程含线程池中的线程 。VMThread线程的角色是一个超级线程可以理解为JVM里面的线程母体或者所有线程的大总管。 VMThread是一个单例的对象最原始的线程所有其他的线程都由这个超级线程产生或触发。 VMThread线程负责完成一些基础性的VM工作比如 VMThread线程可以协调其它线程达到全局安全点。 什么是全局安全点 JVM可以安全地进行一些全局性的操作如GC、偏向锁解除等。在到达全局安全点后 JVM中的所有工作的用户线程都会被挂起只有垃圾收集的native线程会持续不断地跑。也就是说全局安全点会触发JVM的STWStop The World停顿。所有的用户线程都会被暂停没有任何响应有点像卡死的感觉才称为STW停顿。 有哪些场景需要让JVM进入到全局安全点呢主要的场景如下 垃圾回收。偏向锁解除。由于代码优化所引起的指令重排。 JVM设置一个global safe point标志位各用户线程主动去检查这个标志位发现全局安全点标志位为true时就将自己挂起。JVM中所有的用户线程都到达安全点之后此时所有的用户线程都已经挂起 JVM处于STW停顿状态 JVM也达到一个全局安全点。可以简单地把用户线程的安全点理解为局部安全点而把JVM中所有的用户线程都到达局部安全点之后 JVM所处的状态称为全局安全点。 **结论**偏向锁的撤销操作需要依赖JVM的全局安全点从而会带来STW停顿。如果偏向锁撤销操作发生频繁会招来频繁的STW从而导致严重的性能问题。所以对于高并发应用来说一般建议关闭偏向锁。具体的方式可以在启动命令中加上以下JVM参数-XX:-UseBiasedLocking关闭偏向锁之后 Java内置锁默认会进入轻量级锁状态。 轻量级锁的原理 引入轻量级锁的主要目的是在多线程竞争不激烈的情况下通过CAS机制竞争锁减少重量级锁产生的性能损耗。重量级锁使用了操作系统底层的互斥锁Mutex Lock会导致线程在用户态和核心态之间频繁切换从而带来较大的性能损耗。 轻量级锁是一种自旋锁因为JVM本身就是一个应用所以希望在应用层面上通过自旋解决线程同步问题。 普通自旋锁指当有线程来竞争锁时抢锁线程会在原地循环等待而不是被阻塞直到那个占有锁的线程释放锁之后这个抢锁线程才可以获得锁。 锁在原地循环等待的时候是会消耗CPU的 适用于那些临界区代码耗时很短的场景这样线程在原地等待很短的时间就能够获得锁了。 默认情况下自旋的次数为10次 。用户可以通过-XX:PreBlockSpin选项来进行更改。自适应自旋锁 自适应自旋解决的是“锁竞争时间不确定”的问题。 总的思想是根据上一次自旋的时间与结果调整下一次自旋的时间。 谓自适应自旋锁就是等待线程空循环的自旋次数并非是固定的而是会动态地根据实际情况来改变自旋等待的次数自旋次数由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。轻量级锁也被称为非阻塞同步、乐观锁因为这个过程并没有把线程阻塞挂起而是让线程空循环等待 。自适应自旋锁的大概原理是 如果抢锁线程在同一个锁对象上之前成功获得过锁那么JVM就会认为这次自旋也很有可能再次成功因此允许自旋等待持续相对更长的时间。如果对于某个锁抢锁线程在很少成功获得过那么JVM将可能减少自旋时间甚至省略自旋过程以避免浪费处理器资源。 轻量级锁的膨胀 轻量级锁的问题在哪里呢虽然大部分临界区代码的执行时间都是很短的 但是也会存在执行得很慢的临界区代码。临界区代码执行耗时较长在其执行期间其他线程都在原地自旋等待会空消耗CPU。因此如果竞争这个同步锁的线程很多就会有多个线程在原地等待继续空循环消耗CPU空自旋这会带来很大的性能损耗。 轻量级锁本意是为了减少多线程进入操作系统底层的互斥锁 Mutex Lock的概率。所以在争用激烈的场景下轻量级锁会膨胀为基于操作系统内核互斥锁实现的重量级锁。 重量级锁原理 在JVM中每个对象都关联一个监视器这里的对象包含了Object实例和Class实例。监视器是一个同步工具相当于一个许可证拿到许可证的线程即可以进入临界区进行操作没有拿到则需要阻塞等待。重量级锁通过监视器的方式保障了任何时间只允许一个线程通过受到监视器保护的临界区代码。 在Hotspot虚拟机中 监视器是由C类ObjectMonitor 实现的。竞争访问临界区时所有请求锁的线程首先被放在这个竞争队列中。被阻塞的队列放入阻塞队列中。线程的阻塞或者唤醒都需要操作系统来帮忙进程需要从用户态切换到内核态。 用户态是应用程序运行的空间为了能访问到内核管理的资源例如CPU、内存、 I/O可以通过内核态所提供的访问接口实现这些接口就叫系统调用。 由于JVM轻量级锁使用CAS进行自旋抢锁这些CAS操作都处于用户态下进程不存在用户态和内核态之间的运行切换因此JVM轻量级锁开销较小。而JVM重量级锁使用了Linux内核态下的互斥锁Mutex这是重量级锁开销很大的原因。 synchronized的执行过程 抢锁时先判断是否是偏向锁如果是再判断Mark Word中线程ID是否是抢锁线程ID如果是抢锁成功开始执行临界区代码。 如果如果Mark Word中线程ID并未指向抢锁线程就通过CAS操作竞争锁。 如果竞争成功就将Mark Word中线程ID设置为抢锁线程。如果CAS操作竞争失败就说明发生了竞争撤销偏向锁进而升级为轻量级锁。 JVM使用CAS将锁对象的Mark Word替换为抢锁线程的锁记录指针如果成功抢锁线程就获得锁。如果替换失败就表示其他线程竞争锁 JVM尝试使用CAS自旋替换抢锁线程的锁记录指针如果自旋成功抢锁成功那么锁对象依然处于轻量级锁状态。如果JVM的CAS替换锁记录指针自旋失败轻量级锁膨胀为重量级锁后面等待锁的线程也要进入阻塞状态。 总体来说偏向锁是在没有发生锁争用的情况下使用一旦有了第二个线程的争用锁偏向锁就会升级为轻量级锁如果锁争用很激烈轻量级锁的CAS自旋到达阈值后超过最大自旋数量轻量级锁就会升级为重量级锁。 线程间的通信 线程是操作系统调度的最小单位如果每个线程间都孤立地运行就会造资源浪费。线程的通信可以被定义为当多个线程共同操作共享的资源时线程间通过某种方式互相告知自己的状态以避免无效的资源争夺。 “等待通知”通信方式是Java中使用普遍的线程间通信方式其经典的案例就是“生产者消费者”模式。 Java语言中“等待通知”方式的线程间的通信使用对象的wait()、 notify()两类方法来实现。每个Java对象都有wait()、 notify()两类实例方法属于Object对象的方法。 wait()方法对象的wait()方法的主要作用是让当前线程阻塞并等待被唤醒。使用wait()方法时也一定需要放在同步块中线程进入阻塞队列等待唤醒 wait(long timeout) 限时等待版本指定的时间timeout用完线程不再等待被唤醒。 notify()方法 唤醒在等待的线程。使用notify()方法时也需要放在同步块中。 notify()方法的主要作用如下 locko.notify()调用后唤醒locko监视器等待集中的第一个等待线程被唤醒的线程进入EntryList其状态从WAITING等待状态变成BLOCKED。locko.notifyAll()被调用后唤醒locko监视器等待集中的全部等待线程所有被唤醒的线程进入EntryList线程状态从WAITING等待状态变成BLOCKED。EntryList中的线程抢夺到监视器Owner权利之后线程的状态从BLOCKED变成Runnable具备重新执行的资格。 需要在 synchronized 同步块的内部使用 wait 和 notify在调用同步对象的wait()和notify()系列方法时“当前线程”必须拥有该对象的同步锁也就是说 wait()和notify()系列方法需要在同步块中使用否则JVM会抛出非法监视器状态异常。 使用wait()方法时使用while进行条件判断如果是在某种条件下进行等待对条件的判断不能使用if语句做一次性判断而是使用while循环进行反复判断。只有这样才能在线程被唤醒后继续检查wait的条件并在条件没有满足的情况下继续等待。 public T fetch() throws Exception {while (amount 0){ // 不能改成 if 如果if被唤醒之后不会再次判断amountsynchronized (NOT_EMPTY){Print.tcfo(队列已经空了 );//等待未空通知NOT_EMPTY.wait();}}//省略其他 } 文章转载自: http://www.morning.fxqjz.cn.gov.cn.fxqjz.cn http://www.morning.ydxg.cn.gov.cn.ydxg.cn http://www.morning.jcypk.cn.gov.cn.jcypk.cn http://www.morning.lznfl.cn.gov.cn.lznfl.cn http://www.morning.roymf.cn.gov.cn.roymf.cn http://www.morning.rkbly.cn.gov.cn.rkbly.cn http://www.morning.rmfh.cn.gov.cn.rmfh.cn http://www.morning.fcftj.cn.gov.cn.fcftj.cn http://www.morning.qgcfb.cn.gov.cn.qgcfb.cn http://www.morning.xwbld.cn.gov.cn.xwbld.cn http://www.morning.cwqrj.cn.gov.cn.cwqrj.cn http://www.morning.mrckk.cn.gov.cn.mrckk.cn http://www.morning.sdhmn.cn.gov.cn.sdhmn.cn http://www.morning.ypdmr.cn.gov.cn.ypdmr.cn http://www.morning.wncb.cn.gov.cn.wncb.cn http://www.morning.svrud.cn.gov.cn.svrud.cn http://www.morning.ldpjm.cn.gov.cn.ldpjm.cn http://www.morning.gxhqt.cn.gov.cn.gxhqt.cn http://www.morning.txtgy.cn.gov.cn.txtgy.cn http://www.morning.qpzjh.cn.gov.cn.qpzjh.cn http://www.morning.lizpw.com.gov.cn.lizpw.com http://www.morning.mfxcg.cn.gov.cn.mfxcg.cn http://www.morning.dpbgw.cn.gov.cn.dpbgw.cn http://www.morning.jcxyq.cn.gov.cn.jcxyq.cn http://www.morning.bpmmq.cn.gov.cn.bpmmq.cn http://www.morning.xjnw.cn.gov.cn.xjnw.cn http://www.morning.mhlsx.cn.gov.cn.mhlsx.cn http://www.morning.hnk25076he.cn.gov.cn.hnk25076he.cn http://www.morning.ppdr.cn.gov.cn.ppdr.cn http://www.morning.bwygy.cn.gov.cn.bwygy.cn http://www.morning.chongzhanggui.cn.gov.cn.chongzhanggui.cn http://www.morning.lchtb.cn.gov.cn.lchtb.cn http://www.morning.jfmjq.cn.gov.cn.jfmjq.cn http://www.morning.ckntb.cn.gov.cn.ckntb.cn http://www.morning.dfqmy.cn.gov.cn.dfqmy.cn http://www.morning.trhlb.cn.gov.cn.trhlb.cn http://www.morning.zbqry.cn.gov.cn.zbqry.cn http://www.morning.rxnxl.cn.gov.cn.rxnxl.cn http://www.morning.tdfyj.cn.gov.cn.tdfyj.cn http://www.morning.ypmqy.cn.gov.cn.ypmqy.cn http://www.morning.bsbcp.cn.gov.cn.bsbcp.cn http://www.morning.plqkz.cn.gov.cn.plqkz.cn http://www.morning.mkccd.cn.gov.cn.mkccd.cn http://www.morning.ruifund.com.gov.cn.ruifund.com http://www.morning.ggcjf.cn.gov.cn.ggcjf.cn http://www.morning.wschl.cn.gov.cn.wschl.cn http://www.morning.xxlz.cn.gov.cn.xxlz.cn http://www.morning.wwznd.cn.gov.cn.wwznd.cn http://www.morning.jbpodhb.cn.gov.cn.jbpodhb.cn http://www.morning.ppllj.cn.gov.cn.ppllj.cn http://www.morning.dkfb.cn.gov.cn.dkfb.cn http://www.morning.flfxb.cn.gov.cn.flfxb.cn http://www.morning.hsrch.cn.gov.cn.hsrch.cn http://www.morning.rcttz.cn.gov.cn.rcttz.cn http://www.morning.hlxpz.cn.gov.cn.hlxpz.cn http://www.morning.fpryg.cn.gov.cn.fpryg.cn http://www.morning.zmwzg.cn.gov.cn.zmwzg.cn http://www.morning.baohum.com.gov.cn.baohum.com http://www.morning.bnmrp.cn.gov.cn.bnmrp.cn http://www.morning.hqbk.cn.gov.cn.hqbk.cn http://www.morning.ktnmg.cn.gov.cn.ktnmg.cn http://www.morning.nwjzc.cn.gov.cn.nwjzc.cn http://www.morning.rxnxl.cn.gov.cn.rxnxl.cn http://www.morning.dtzxf.cn.gov.cn.dtzxf.cn http://www.morning.rqxmz.cn.gov.cn.rqxmz.cn http://www.morning.wnywk.cn.gov.cn.wnywk.cn http://www.morning.bpmfq.cn.gov.cn.bpmfq.cn http://www.morning.bsghk.cn.gov.cn.bsghk.cn http://www.morning.dxtxk.cn.gov.cn.dxtxk.cn http://www.morning.nhrkl.cn.gov.cn.nhrkl.cn http://www.morning.jzykq.cn.gov.cn.jzykq.cn http://www.morning.shuangxizhongxin.cn.gov.cn.shuangxizhongxin.cn http://www.morning.ykgp.cn.gov.cn.ykgp.cn http://www.morning.qsxxl.cn.gov.cn.qsxxl.cn http://www.morning.sprbs.cn.gov.cn.sprbs.cn http://www.morning.rwmqp.cn.gov.cn.rwmqp.cn http://www.morning.sbjhm.cn.gov.cn.sbjhm.cn http://www.morning.bsbcp.cn.gov.cn.bsbcp.cn http://www.morning.swzpx.cn.gov.cn.swzpx.cn http://www.morning.ftsmg.com.gov.cn.ftsmg.com 查看全文 http://www.tj-hxxt.cn/news/279974.html 相关文章: 蒙文网站建设情况汇报材料着陆页制作网站 学校网站建设规范做投票链接网站 视频分享网站怎么做的wordpress研究 旅游类网站开发设计报告国外网站建设费用 公司变更股东的流程及所提交的材料网站seo排名优化价格 国家建设局网站首页怎么做万网网站 济南好的网站建设公司排名深圳社区网 做营销网站设计网络规划设计师教程第2版下载 做免费资料分享网站会不会涉及版权龙山县建设局网站 可以发布广告的网站成都企业建站系统 泰州网站关键词优化软件咨询定制网站开发接私活 去公司叫自己做网站不会做电商网站 服务器 一个网站源码值多少钱做1688网站需要懂英语吗 一定火网站建设定制弹窗网站制作 站长之家是什么色轮 网站 常州自助建站seo网上注册公司在哪里 网站开发与软件开发的区别微网站建设哪家好 百度做网站不给FTP密码保险公司网站 松原企业网站建设网页版 php做简易网站三门网站建设 商城网站制作的教程黑龙江住房建设部网站 做外贸找客户最好用的网站中文wordpress主题下载 重庆旅游seo整站优化素材 阿里巴巴怎么做不花钱的网站宿迁经济技术开发区 网站制作的服务机构网络营销的主要传播渠道是 知识产权教育网站建设班级优化大师官网 网站查询页面设计wdcp 配置网站 商务网站建设与推广实训意义dll网站服务 网站关键词优化怎么做国内可以上的网站 做建站较好的网站沧州南皮网站建设