皮皮网
皮皮网

【c 屏保 源码】【nioworker源码解析】【源码授权程序】clh源码

来源:池化rtl源码 项目 发表时间:2024-11-27 05:58:00

1.Java多线程:JUC并发工具原理
2.2024 年互联网大厂 Java 工程师高级面试八股文汇总(1120 道题目附解析)
3.后端面经-JavaAQS详解
4.急,病毒有什么危害?详细

clh源码

Java多线程:JUC并发工具原理

       ä¸€.前言

       è¶ç€æœ‰ç©º,赶紧把之前欠的债还上.这是多线程一阶段计划的最后一篇,后续多线程会转入修订和深入阶段.彻底吃透多线程.

二.工具介绍

       ä¹‹å‰è¯´AQS的时候曾经提到过这几个类,这几个类有一些各自的特点,很符合特定的场景,之前在生产上用的还挺舒服.

       æˆ‘们一般使用的并发工具有四种:

       CyclicBarrier:放学一起走

       å…è®¸ä¸€ç»„线程互相等待,直到到达某个公共屏障点(commonbarrierpoint)

       è®©ä¸€ç»„线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活

       CountDownLatch:等人到齐了就触发

       åœ¨å®Œæˆä¸€ç»„正在其他线程中执行的操作之前,它允许一个或多个线程一直等待

       ç”¨ç»™å®šçš„计数初始化CountDownLatch。

       ç”±äºŽè°ƒç”¨äº†countDown()方法,所以在当前计数到达零之前,await方法会一直受阻塞。

       ä¹‹åŽï¼Œä¼šé‡Šæ”¾æ‰€æœ‰ç­‰å¾…的线程,await的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。

       CountDownLatch是通过一个计数器来实现的,当我们在new一个CountDownLatch对象的时候需要带入该计数器值,该值就表示了线程的数量。

       æ¯å½“一个线程完成自己的任务后,计数器的值就会减1。当计数器的值变为0时,就表示所有的线程均已经完成了任务

       Semaphore

       ä¿¡å·é‡Semaphore是一个控制访问多个共享资源的计数器,和CountDownLatch一样,其本质上是一个“共享锁”。

       Exchanger

       å¯ä»¥åœ¨å¯¹ä¸­å¯¹å…ƒç´ è¿›è¡Œé…å¯¹å’Œäº¤æ¢çš„线程的同步点

       æ¯ä¸ªçº¿ç¨‹å°†æ¡ç›®ä¸Šçš„某个方法呈现给exchange方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象,Exchanger可能被视为SynchronousQueue的双向形式

三.原理解析3.1CyclicBarrier

       ä½œç”¨:

       å®ƒå…è®¸ä¸€ç»„线程互相等待,直到到达某个公共屏障点(CommonBarrierPoint)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时CyclicBarrier很有用。因为该Barrier在释放等待线程后可以重用,所以称它为循环(Cyclic)的屏障(Barrier)。

       å†…部原理:

       å†…部使用重入锁ReentrantLock和Condition

       æž„造函数:

       CyclicBarrier(intparties):

       åˆ›å»ºä¸€ä¸ªæ–°çš„CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,

       ä½†å®ƒä¸ä¼šåœ¨å¯åŠ¨barrier时执行预定义的操作。

       CyclicBarrier(intparties,RunnablebarrierAction):

       åˆ›å»ºä¸€ä¸ªæ–°çš„CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,

       å¹¶åœ¨å¯åŠ¨barrier时执行给定的屏障操作,该操作由最后一个进入barrier的线程执行。

       ä½¿ç”¨å˜é‡:

       parties变量:表示拦截线程的总数量。

       count变量:表示拦截线程的剩余需要数量。

       barrierAction变量:为CyclicBarrier接收的Runnable命令,用于在线程到达屏障时,优先执行barrierAction,用于处理更加复杂的业务场景。

       generation变量:表示CyclicBarrier的更新换代

//常用方法:M-await:等待状态M-await(longtimeout,TimeUnitunit):等待超时M-dowait-该方法第一步会试着获取锁-如果分代已经损坏,抛出异常-如果线程中断,终止CyclicBarrier-进来线程,--count-count==0表示所有线程均已到位,触发Runnable任务-唤醒所有等待线程,并更新generation>跳出等待状态的方法-最后一个线程到达,即index==0-超出了指定时间(超时等待)-其他的某个线程中断当前线程-其他的某个线程中断另一个等待的线程-其他的某个线程在等待barrier超时-其他的某个线程在此barrier调用reset()方法。reset()方法用于将屏障重置为初始状态。SC-Generation:描述了CyclicBarrier的更新换代。-在CyclicBarrier中,同一批线程属于同一代。-当有parties个线程全部到达barrier时,generation就会被更新换代。-其中broken属性,标识该当前CyclicBarrier是否已经处于中断状态M-breakBarrier:终止所有的线程M-nextGeneration:更新换代操作-1.唤醒所有线程。-2.重置count。-3.重置generation。M-reset:重置barrier到初始化状态M-getNumberWaiting:获得等待的线程数M-判断CyclicBarrier是否处于中断

       ä½¿ç”¨æ¡ˆä¾‹:

       GiteeCyclicBarrier使用

       é—®é¢˜è¡¥å……:

//问题一:拦截的核心1.传入总得Count数2.每次进来都会--count,同时判断count==.如果不为0,当前线程就会阻塞//问题二:涉及源码privatefinalReentrantLocklock=newReentrantLock();privatefinalConditiontrip=lock.newCondition();3.2CountDownLatch

       åœ¨å®Œæˆä¸€ç»„正在其他线程中执行的操作之前,它允许一个或多个线程一直等待

       ç”¨ç»™å®šçš„计数初始化CountDownLatch。由于调用了countDown()方法,所以在当前计数到达零之前,await方法会一直受阻塞。之后,会释放所有等待的线程,await的所有后续调用都将立即返回。这种现象只出现一次,计数无法被重置。如果需要重置计数,请考虑使用CyclicBarrier。

       CountDownLatch是通过一个计数器来实现的,当我们在new一个CountDownLatch对象的时候需要带入该计数器值,该值就表示了线程的数量。每当一个线程完成自己的任务后,计数器的值就会减1。当计数器的值变为0时,就表示所有的线程均已经完成了任务

//内部主要方法>CountDownLatch内部依赖Sync实现,而Sync继承AQS>sync::tryAcquireShared获取同步状态:tryReleaseShared释放同步状态>await():使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断:sync.acquireSharedInterruptibly(1);:内部使用AQS的acquireSharedInterruptibly(intarg)>getState():获取同步状态,其值等于计数器的值:从这里我们可以看到如果计数器值不等于0,则会调用doAcquireSharedInterruptibly(intarg)>doAcquireSharedInterruptibly:自旋方法会尝试一直去获取同步状态>countDown:CountDownLatch提供countDown()方法递减锁存器的计数,如果计数到达零,则释放所有等待的线程:内部调用AQS的releaseShared(intarg)方法来释放共享锁同步状态:tryReleaseShared(intarg)方法被CountDownLatch的内部类Sync重写

       å‚考案例

       GiteeCountDownLatch使用

       æ€»ç»“

       CountDownLatch内部通过共享锁实现。在创建CountDownLatch实例时,需要传递一个int型的参数:count,该参数为计数器的初始值,也可以理解为该共享锁可以获取的总次数。

       å½“某个线程调用await()方法,程序首先判断count的值是否为0,如果不会0的话则会一直等待直到为0为止(PS:可以多个线程都调用await)

       å½“其他线程调用countDown()方法时,则执行释放共享锁状态,使count值–1(PS:countDown并不会阻塞)

       å½“在创建CountDownLatch时初始化的count参数,必须要有count线程调用countDown方法才会使计数器count等于0,锁才会释放,前面等待的线程才会继续运行。注意CountDownLatch不能回滚重置

3.3Semaphore

       åŸºç¡€ç‚¹

       ä¿¡å·é‡Semaphore是一个控制访问多个共享资源的计数器,和CountDownLatch一样,其本质上是一个“共享锁”。

       ä»Žæ¦‚念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire(),然后再获取该许可。每个release()添加一个许可,从而可能释放一个正在阻塞的获取者。

       Semaphore通常用于限制可以访问某些资源(物理或逻辑的)的线程数目

       å½“一个线程想要访问某个共享资源时,它必须要先获取Semaphore,当Semaphore>0时,获取该资源并使Semaphore–1。如果Semaphore值=0,则表示全部的共享资源已经被其他线程全部占用,线程必须要等待其他线程释放资源。当线程释放资源时,Semaphore则+1

       å®žçŽ°ç»†èŠ‚

       Semaphore提供了两个构造函数:

       Semaphore(intpermits):创建具有给定的许可数和非公平的公平设置的Semaphore。

       Semaphore(intpermits,booleanfair):创建具有给定的许可数和给定的公平设置的Semaphore。

       Semaphore默认选择非公平锁。

       å½“信号量Semaphore=1时,它可以当作互斥锁使用。其中0、1就相当于它的状态,当=1时表示其他线程可以获取,当=0时,排他,即其他线程必须要等待。

//------信号量获取>acquire()方法来获取一个许可:内部调用AQS的acquireSharedInterruptibly(intarg),该方法以共享模式获取同步状态>公平:判断该线程是否位于CLH队列的列头:获取当前的信号量许可:设置“获得acquires个信号量许可之后,剩余的信号量许可数”:CAS设置信号量>非公平:不需要判断当前线程是否位于CLH同步队列列头3.4Exchanger

       å¯ä»¥åœ¨å¯¹ä¸­å¯¹å…ƒç´ è¿›è¡Œé…å¯¹å’Œäº¤æ¢çš„线程的同步点

       æ¯ä¸ªçº¿ç¨‹å°†æ¡ç›®ä¸Šçš„某个方法呈现给exchange方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象,Exchanger可能被视为SynchronousQueue的双向形式

       Exchanger,它允许在并发任务之间交换数据:当两个线程都到达同步点时,他们交换数据结构,因此第一个线程的数据结构进入到第二个线程中,第二个线程的数据结构进入到第一个线程中

       TODO:Exchanger的源代码比较绕,而且这个组件使用场景并不多,所以先留个坑,以后项目上真的有场景了再实际上分析一下

3.5并发工具使用

       @github.com/black-ant/case/tree/master/case%Module%Thread/case%thread_utils

补充:#CountDownLatch和CyclicBarrier如何理解?

       CyclicBarrier:小学生去郊游,老师下车时统计人数,人数到齐了才能一起参观

       CountDownLatch:幼儿园老师送孩子(ChildThread)放学,走一个记一个数,当所有的学生放学后,老师(BossThread)下班

//核心解释:CyclicBarrier就是一堵墙,人数到了所有线程才能一起越过墙CountDownLatch只是一个计数器,数目到了主线程才能执行//其他要点:CyclicBarrier可以重置计数,CountDownLatch不可以总结

       ç»ˆäºŽè¡¥ä¸Šäº†æœ€åŽä¸€å—板,后面来真正的深入多线程看看吧,争取早日成为多线程大师段位

更新记录

       :优化布局

       ä½œè€…:AntBlack

年互联网大厂 Java 工程师高级面试八股文汇总( 道题目附解析)

       面对年的互联网大厂招聘面试,形势变得越来越严峻。腾讯、字节跳动等知名大厂的面试名额显著减少,而面试标准却在不断提高。c 屏保 源码因此,如果求职者在准备面试时不够用心,很可能就会在面试官面前哑口无言,甚至失去获得心仪offer的机会。

       当前的就业环境充满着不确定性,对于希望在金九银十期间跳槽并获得加薪的求职者来说,在面试前做好充分准备显得尤为重要!

       在大厂面试中,面试者往往会遇到一些看似困难、实际与自己准备的“题库”不符的问题。不知道如何入手,让面试过程变得棘手。

       为了在面试中脱颖而出,求职者需要深入理解和掌握面试的必考点和常见套路。今天,我们为大家整理了针对Java工程师的高级面试题,包括但不限于Java基础、JVM、多线程、Mysql、Spring系列、Dubbo、Mybatis、Redis、网络知识、Linux、RabbitMQ、Zookeeper、Netty、大数据技术、算法与设计模式、实战项目等多方面内容。无论你是应届毕业生、实习生还是nioworker源码解析有工作经验的求职者,都可以从中找到有价值的参考。

       为了适应篇幅限制,我们以截图主要内容的形式提供这部分内容供参考,需要完整版本的求职者可以通过点击传送门获取。

       为了帮助求职者更好地应对面试,以下是针对Java工程师高级面试的详细内容概览:

       Java基础(技术干货+面试题):涵盖基础语法、面向对象、类与接口、变量与方法、内部类、重写与重载、IO流、反射等。

       JVM(底层原理+面试题):涉及JVM内存区域、JVM运行时内存、垃圾回收与算法、JAVA四种引用类型、GC垃圾收集器、JVM类加载机制、GC分代收集算法、分区收集算法等。

       多线程(底层原理+面试题):包含多线程与高并发基础概念、JUC同步工具、同步容器、线程池、线程顺序执行控制、纤程、JMH、引用类型、Disruptor等。

       Mysql(技术干货+面试题):覆盖数据类型、引擎、索引、事务、锁、视图、存储过程与函数、触发器、常用SQL语句、源码授权程序SQL优化、常见面试题等。

       Spring系列(底层原理+面试题):包括Spring常用注解、IOC原理、APO原理、MVC原理、Spring Boot原理、CAP原理和BASE理论、面试题等。

       Dubbo(底层原理+面试题):涉及SPI机制、自适应拓展原理、服务导出、服务引用、集群容错之Directory、集群容错之Router、集群容错之Cluster、集群容错之LoadBalance、服务调用过程等。

       Mybatis(底层原理+面试题):包含实现原理、映射文件、动态SQL、缓存机制、配置文件加载源码、MAPPERPROXY创建源码、EXECUTOR源码等。

       Redis(底层原理+面试题):涉及Redis数据类型、持久化、内存相关、分布式问题等。

       网络知识(底层原理+面试题):涵盖计算机网络体系结构、网络协议、网络7层架构、TCP/IP原理、HTTP原理、CDN原理、RPC、负载均衡等。

       Linux(底层原理+面试题):包括Linux概述、磁盘、盗号引流源码目录、文件、swap分区等。

       RabbitMQ(底层原理+面试题):包括RabbitMQ基础概念、使用场景、工作模式、消息中间件、经典面试题等。

       Zookeeper(底层原理+面试题):包含Zookeeper文件系统、Zookeeper概念、Chroot特性、会话管理、典型应用场景、ZAB协议、面试题等。

       Netty(底层原理+面试题):涵盖Netty简介、Netty的特点、Netty高性能设计、Netty原理、Netty经典面试题等。

       大数据技术(技术干货+面试题):包含Hadoop、Spark、Storm、YARN、数据复制、数据库并发策略、数据库锁、CLH队列等。

       算法(技术干货+大厂面试题):涉及红黑树、贪心算法、动态规划、七大查找算法、一致性算法、Java算法、数据结构、加密算法、大厂面试题等。

       设计模式(底层原理+技术干货):涵盖单例模式、工厂模式、ddos php 源码建造者模式、原型模式、适配器模式、装饰器模式、代理模式、中介者模式、命令模式等种设计模式。

       实战项目(突击大厂必备):此项目是一款已上线的“网约车”应用,符合我国交通部对网约车监管的技术要求,通过了交通部的线上和线下能力认定。原型曾在杭州上线运行,核心功能包括账户系统、订单系统、支付系统、地图引擎、派单引擎、消息系统等。项目完全采用微服务架构设计,应用了成熟的接口安全方案,采用分布式锁保证数据同步,使用分布式事务解决数据一致性问题。前置技能包括Git、Maven、Spring Boot、Spring Cloud、Redis、Mysql、RabbitMQ、ActiveMQ等。

后端面经-JavaAQS详解

       AQS是什么?

       AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock。简单来说,AQS定义了一套框架,来实现同步类。

       AQS的核心思想是对于共享资源,维护一个双端队列来管理线程,队列中的线程依次获取资源,获取不到的线程进入队列等待,直到资源释放,队列中的线程依次获取资源。AQS的基本框架如图所示:

       资源state变量表示共享资源,通常是int类型。CLH双向队列是一种基于逻辑队列非线程饥饿的自旋公平锁,具体介绍可参考此篇博客。CLH中每个节点都表示一个线程,处于头部的节点获取资源,而其他资源则等待。Node的方法和属性值如图所示:其中,

       一般来说,一个同步器是资源独占模式或者资源共享模式的其中之一,因此tryAcquire(int)和tryAcquireShared(int)只需要实现一个即可,tryRelease(int)和tryReleaseShared(int)同理。但是同步器也可以实现两种模式的资源获取和释放,从而实现独占和共享两种模式。

       acquire(int)是获取资源的顶层入口,tryAcquire(int)是获取资源的方法,需要自定义同步器实现。addWaiter(Node.EXCLUSIVE)是将线程加入等待队列的尾部,acquireQueued(Node node, int arg)将线程阻塞在等待队列中,直到获取到资源后才返回。

       release(int)是释放资源的顶层入口方法,tryRelease(int)是释放资源的方法,需要自定义同步器自己实现。unparkSuccessor(h)是唤醒后继节点的方法。

       acquireShared(int)和releaseShared(int)是使用共享模式获取共享资源的顶层入口方法,tryAcquireShared(arg)是获取共享资源的方法,doAcquireShared(arg)将线程阻塞在等待队列中,直到获取到资源后才返回。releaseShared(int)是释放共享资源的顶层入口方法,doReleaseShared()方法释放共享资源。

       面试问题模拟:AQS是接口吗?有哪些没有实现的方法?看过相关源码吗?

       A:AQS定义了一个实现同步类的框架,实现方法主要有tryAquire和tryRelease,表示独占模式的资源获取和释放,tryAquireShared和tryReleaseShared表示共享模式的资源获取和释放。源码分析如上文所述。

急,病毒有什么危害?详细

       1.消耗资源

        所有计算机病毒都是程序,是程序,则在运行的时候都要占用系统资源。很多病毒都是驻留内存的,也就是说,它们会长期占用系统资源。这必然会造成系统的缓慢。即使是无害的病毒,也会有这个问题——因为它也是程序。这种危害看起来似乎不会造成什么损失,其实不然。年莫里斯编的蠕虫病毒,实际上不具有什么实质性的破坏作用,但它耗费了大量的系统资源,从而使系统极度缓慢直至停止运行。这样的损失实际上是时间的损失。现在,也有像I LOVE YOU这样的病毒,采用耗费系统或网络资源的方式作为破坏的一种手段。

       2.干扰输出

        在屏幕上显示图形或符号,或播放莫名其妙的音乐或声音。一般的无害病毒都有这项“功能”,这可能也是无害病毒的主要“攻击”手段了。这样的攻击手段通常不会带来什么实质性的破坏,但却会干扰你的工作。比如一个叫做“零臭虫”(Zero Bug)的病毒,在它进入内存后,会在屏幕上显示一个“臭虫”。这个“臭虫”会“吃掉”屏幕上所有的“O”字符。这个病毒不会使文件数据丢失,不过看一个没有“O”的屏幕是有相当难度的。恶性病毒也有可能改变屏幕显示或播放声音,但通常此时只是灾难的开始——它也许正在格式化你的硬盘。

       3.干扰输入

        对你的键盘做手脚。无论是无害病毒还是恶性病毒都有可能具有这项“功能”。这种破坏方式会使你的键盘输入出现混乱。比如“排字工”病看(Type COM)就是一种可以干扰键盘输入的病毒。当你输入“A”的时候,却会在屏幕上显示“S”;当你在输入“L”的时候,却会显示“:”。总之,实际被计算机接收的字符是你所按键的右边那个键。又如“Hymn”病毒,在病毒进入内存之后,就监视键盘活动,在第次敲击键盘之后,再敲击的键依次被两个空格和五个乱码代替,这样就使键盘无法发挥作用。

       4.破坏信息

        这是恶性病毒的主要破坏手段之一。破坏文件的方式有多种。

        在病毒感染文件时,可以说已经对文件产生了一些破坏。尤其是一些病毒,它们为了在感染文件后不增加文件长度,硬是用自己的代码将宿主程序的一部分代码覆盖。有时这样做就会对文件造成破坏。但这种破坏并不是病毒的目的,设计得好的病毒也会尽量避免这种破坏以隐蔽自己。

        有些病毒会破坏磁盘的文件分配表(FAT)。文件分配表是磁盘文件信息储存的一个缩影,在其中记录着所有文件的位置和大小,是文件名与文件信息的纽带。如果FAT遭到破坏,使用DIR等命令仍可以见原有文件。但你会发现这些仍然“存在”的文件已经无法使用了。

        有些病毒会修改一些储存数据的文件。这些文件的格式不变,也还能被读取,但内容却变了。比如一个WORD文档,里面储存着某人的成绩单。本来是分却被病毒改成了分。在调用这个文件时,WORD不会报告任何出错信息,但实际上里面的内容已经被破坏了——这样的改变更难以发现。上面的例子不会造成什么重大后果,但如果这个文件里储存的是重要的军事或金融数据,若被更改其后果不堪设想。

        有些病毒会格式化磁盘。这是病毒破坏文件的极端手段,也是造成损失最大的一种。在磁盘被格式化以后,文件储存全部清除。很多恶性病毒的破坏方式都是格式化磁盘。但格式化磁盘需要时间——如果你在病毒发作时及时关机,可能还能保住部分文件。

        5.泄露信息

        最近流行的SirCam、求职信、红色代码、尼姆达等病毒均有泄露信息的特点。SirCam和求职信病毒泄露信息的方式是把被感染机器上的一些文件作为邮件附件连同病毒一起发往一些真实的电子邮件地址。红色代码和尼姆达病毒泄露信息的方式是把被感染机器的一些硬盘分区设成远程共享,等于是后门大开。在红色代码病毒流行期间,就出现了一些机器被红色代码病毒感染了以后,黑客借助被打开的后门又实施了篡改网页的二次破坏的情况。

        6.破坏系统

        这也是一种严重的破坏行为。病毒可以来用篡改系统设置或对系统进行加密的方法,使系统发生混乱。赫赫有名的ClH病毒甚至还能破坏硬件系统。它可以识别台湾地区及个另外国家生产的某些计算机主板上的BlOS(基本输入输出系统)的写入口,并随机修改几个字符,造成BlOS工作混乱。由于BIOS在计算机中的特殊地位,它必须靠专业厂商才能修复。这样,就造成了硬件的损坏。

        有些计算机病毒还具有感知杀毒软件的能力,先下手干掉已经安装在宿主机器内的杀毒软件。比如最近流行的求职信病毒的新变种就有这样的特点。

        7.阻塞网络

        红色代码、尼姆达这类新的蠕虫类病毒,在确定下一个感染目标之前,要向网上的其他lP地址发出大量的试探性攻击包,对相应的主机进行漏洞探测。每一个因为有漏洞而新近被感染的主机也都会加入这个行列。在这种类型的漏洞普遍存在的情况下,会出现一种滚雪球一样的连锁效应,导致一些网络被这种试探性攻击包所拥塞,因而正常的网络通信受到阻碍,乃至瘫痪。

        8.心理影响

       计算机病毒不仅对计算机产生影响,而且对人也会产生一定影响。当然我们说过,计算机病毒是不会与人交叉感染的,那么它是怎样对人产生影响的呢?其实很简单,它是通过控制屏幕的输出来对人的心理进行影响的。有些按破坏能力分类归为“无害”的病毒,虽然不会损坏数据,但在发作时并不只是播放一段音乐这样简单。有些病毒会进行反动宣传,有些病毒会显示一些对人身心健康不利的文字或图像。在年年底,人们发现了一个通过电子邮件传播的病毒:“女鬼”病毒。当你打开感染了“女鬼”病毒的邮件的附件时,病毒发作,在屏幕上显示一个美食家杀害妻子的恐怖故事。之后,一切恢复正常。一般人会以为这个病毒的发作只是这样而已。但是,5分钟后,突然屏幕变黑,一个恐怖的女尸的图像就会显示出来,让没有丝毫心理准备的人吓一跳。据报道,一人因此突发心脏病身亡。所以,计算机病毒的这个危害也是不可小视的。

相关栏目:焦点