欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    第10章 java 多线程编程.doc

    • 资源ID:79333912       资源大小:207.50KB        全文页数:15页
    • 资源格式: DOC        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    第10章 java 多线程编程.doc

    第10章 多线程2总体概要2相关知识2学习重点2内容框架210.1多线程的概念210.1.1程序、进程和多任务3(一).程序(program)3(二)多任务310.1.1线程310.1.2多线程310.1.3线程的生命周期与多线程机制4(一)线程的生命周期与状态4(二)java的多线程机制410.2创建线程410.2.1通过继承Thread类创建线程4(一)Thread类的构造方法4(二)Thread类的常用方法5(三)继承Thread类创建线程510.2.2通过实现Runnable接口创建线程7(一)Runnable接口方法7(二)实现Runn Thread和Runnable实现线程8(三) Thread和Runnable实现线程的比较910.3线程的状态转换910.4线程的优先级与调度1010.4.1线程的优先级10(一)Thread类定义了基本3个常数11(二)线程先优级的使用1110.4.2线程的的状态12(一)挂起一个线程12(二)停止一个线程12(三)线程睡眠12(四)线程等待12(五)线程让步13(六)线程加入13(七)线程唤醒1310.5线程的同步1310.6何时使用多线程及注意问题1410.7小结1410.8习题15第10章 多线程总体概要l 了解多线程的概念:程序,进程和多任务l 撑握线程的生命周期l 理解java的多线程机制l 熟练撑握实现线程两种方法:Thread类和Runnable接口以有这两种方法的区别l 熟练撑握Thread类的构造方法和常用方法l 线程优先级和线程调度l 能自己写出自己的多线程程序l 使用线程注意事项相关知识l 线程优先级l 线程的转换l 并发与并行学习重点l 线程的生命周期l 线程的两种方法的实现l 线程之间的状态转换内容框架软件多任务程序线程进程多线程多线程概念相关概念创建线程线程的状态转换Runnable接口线程的优先级,调度,同步Thead类10.1多线程的概念本章介绍java语言的多线程编程的相关知识,java提供了十分强大的多线程实现机制,它使得编程人员可以方便地编写多线程应用程序。在一个应用程序中可以包含多个线程,每一个线程都具有特定的程序功能,并且可以与其他线程并发执行,java提供了Tread类和Runnable接口为多线程提供支持。首选为大家介绍多线程编程的基本概念,以及与多线程有关的概念,如程序,进程,多任务等。10.1.1程序、进程和多任务(一).程序(program)程序是对数据描述与操作的代码的集合,是应用程序执行的脚本进程(process)是程序的一次执行过程,是操作系统运行程序的基本单位,程序是静态的,进程是动态的。系统运行一个程序就是一个进程从创建、运行到消亡的过程。(二)多任务多任务是指在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每一个任务对应一个进行。例如,你一在Window操作系统中打开QQ程序,也打开Word,Eclipse程序。【注意】一个CPU在同一时刻只能执行一个程序的一条指令,实际上,多任务运行的并发机制这些任务交替运行,因间隔时间短,所以你感觉就是多个程序在同时运行。10.1.1线程线程又称为轻量级进程,它是控制线程(thread of control)的缩写.它和进程一样拥有独立的执行控制,由操作系统负责调度,运行一个程序时,程序内部的代码都是按顺序先后执行的,如果能够将一个进程划分为更小的单位,则程序中一些彼此相对独立的代码段可以重叠运行,将会获得更高的执行效率,线程主是解决这个问题.线程是比进程更小的运行单位,是程序中单个顺序的流控制,一个进程中可以包含多个线程。线程是一种特殊的多任务方式,当一个程序执行多线程时,可以运行两个或更多的的同一个程序启动的任务。这样,一个程序可以使得多个活动任务同时发生.。线程与任何一个程序一样有一个开始,一系列可执行的命令序列, 一个结束。在执行的任何时刻,只有一个执行点。线程与程序不周的是线程本身不能运行,它只能包含在程序中,只能在程序中执行。一个线程在程序运行时,必须争取到为自己分配的系统资源,如执行堆栈、程序计数器,等等。10.1.2多线程单个线程没有什么特别的意义,真正有用的是具有多线程的程序.多线程是相对于单线程而言的,指的是在一个程序中可以定义多个线程并发同时运行它们,每个线程可以执行不同的任务。与进程不同的是,同类多线程共享一块内存空间和一组系统资源,所以,系统创建多线程开销相对较小。因此,也称线程为国负荷进程。多线程和伟统的线程在程序设计上最大区别在于,由于各个线程的控制流彼此独立,使行多个线程之间的代码是可以按照任何合理的顺序的执行,由此带来了线程的调度和同步问题.多线程和多任务是两个既有联系又有区别的概念。多任务是针对操作系统而言的,代表着操作系统可以同时执行的程序个数;多线程是针对一个程序而言,代表着一个进程内部可以同时执行的线程个数,而每个线程可以完成不同的任务。多程线的执行是并发的,并发不同于并行,并行是指两个线程并行执行,互不干涉,则并行是指宏观上的“并行”,微观上的“分时复用”,如果系统只有一个CPU,那么真正的并行是不可能的,但是由于CPU的速度非常快,如果采用时间片轮转的方法,用户即可从宏观上感觉多个线程是在“并行” 执行.10.1.3线程的生命周期与多线程机制(一)线程的生命周期与状态线程同进程一样,一个线程也有创建,运行到消亡的过程,这一个过程称为线程的生命周期,使用线程的状态表明线程处于生命周期的哪个阶段。线程有创建(new)、可运行(Runnable)、运行中(Running)、挂起(NotRunnable)、死亡(Dead)5个状态,通过线程的控制和调度可使线程在这几种状态转化。Java语言是利用内在支持多线程,而其它大部分计算机编程语言都是利用外部软件实现的多线程。Java的每一个程序自动拥有一个线程 ,称为主线程。当程序加载到内存时,启动主线程。要加载其它线程,程序就要便 用Thread类或Runnable接口。(二)java的多线程机制java.lang中的线程类Thread封装了所有需要的线程控制,有很多方法用来控制一个线程的运行、休眠、挂起或停止。这就是java的多线程机制。使用java的多线程机制编程可将程序的任务分解为几个并行的子任务,通过线程并发招待来加速程序运行,提 高CPU的利用率。例如,在网總编程囊,有很多功能可以并发执行,网络传输带度一般较慢,用户输入速度也较慢,你可以设计两下独立线程分别完成这两个任务鸸不影响政党的显示或期货功能。在编写动画程序时,你可以用一个线程进行延时,让另一个线程在延时中准备要显示的画面,心实现完美 的动画 显示.10.2创建线程实现多线程的两个方法:通过继承线程类Thread来创建线程类;实现Runnable 接口的类来创建线程。下面分别对这两种方法进行讲解.10.2.1通过继承Thread类创建线程(一)Thread类的构造方法 Thread()分配新的 Thread 对象 Thread(Runnable target)分配新的 Thread 对象 Thread(Runnable target, String name)分配新的 Thread 对象 Thread(String name)分配新的 Thread 对象 Thread(ThreadGroup group, Runnable target)分配新的Thread 对象 Thread(ThreadGroup group, Runnable target, String name) 分配新的 Thread 对象,以便将 target 作为其运行对象,将指定的 name 作为其名称,并作为 group 所引用的线程组的一员 Thread(ThreadGroup group, Runnable target, String name, long stackSize)分配新的 Thread 对象,以便将 target 作为其运行对象,将指定的 name 作为其名称,作为 group 所引用的线程组的一员,并具有指定的堆栈尺寸 Thread(ThreadGroup group, String name)分配新的 Thread对象。(二)Thread类的常用方法 Public static int activeCount() 返回当前线程的线程组中活动线程的数目。 Pubilc String getName()返回该线程的名称。 Pubic int getPriority()返回线程的优先级。 Pubic void run()如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。 Public void interrupt()中断线程。 Public void join(long millis)等待该线程终止的时间最长为millis 毫秒。 Publi void setPriority(int newPriority)更改线程的优先级, 超时为 0 意味着要一直等下去。 Public void start()使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 Public static void yield()暂停当前正在执行的线程对象,并执行其他线程。(三)继承Thread类创建线程【例10.1】在程序中通过继承Thread类创建一个线程子类SonThread,通过TestThread主类同时运行两个线程对象thread1 和thread2,TestThread.java,代码如下所示:package bedeck;import javax.swing.*;import java.awt.*;import java.awt.event.*;/* * application程序 * */public class TestThread extends JFrame implements ActionListenerTextField jtf = new TextField();JLabel jlb = new JLabel("开始按扭即可启动两个线程");JButton jb = new JButton("开始");static String state = "" /记录程序的启动情况/* * 实现两个线程 * */public TestThread()super("线程实例");this.setSize(320, 240);this.setLayout(null);jb.addActionListener(this); /添加单击事件this.add(jlb);jlb.setBounds(10, 10, 190, 20);this.add(jb);jb.setBounds(210, 10, 90, 20);this.add(jtf);jtf.setBounds(10, 50, 290, 80);this.setVisible(true);/* * main()方法 * */public static void main(String a)new TestThread();/* * 实现actionListener接口 * */public void actionPerformed(ActionEvent e)SonThread st1 = new SonThread("Thread1");SonThread st2 = new SonThread("Thread2");jtf.setText("");st1.start();st2.start();jtf.setText(state);class SonThread extends Threadpublic SonThread(String str)super(str); /调用父类的构造public void run()for(int i = 0 ; i<3 ; i+)TestThread.state += "n"+getName() + "在运行n"trysleep(500); /休眠500毫秒确定那个线程在运行TestThread.state += "n"+ getName()+"在休眠n"catch(InterruptedException e)System.out.println(""+e);说明:mian方法是application应用程序起点,main()方法本身也是一个线程,是程序自动拥有的一个线程,称为主程序,Start()方法启动用户创建的两个线程。用户可从结果看出两个线程的名字是交替显示,这是因为两个线程同步的。创建线程其实就是设计run方法,一旦启动线程对象,就进入run方法,便执行run中的所有语句,run方法执行完毕,这个线程也就结束了。InterruptedException,当线程在很长一段时间内一直处于正在等待、休眠或暂停状态,而另一个线程用 Thread 类中的 iterrupt 方法中断它时,抛出该异常。运行结果如10-1所示10-1 Thread类创建线程【注意】用sleep语句进行休眠线程交不占用CPU,基他线程可以继续运行,当休眠被唤醒。继续执行下面的语句继承Thread创建的子类,必须覆盖run()方法10.2.2通过实现Runnable接口创建线程由于java只支持单继承,如果当一个类继承了其他类的时,这时您就不能通过Thread类来创建线程,而是使用Runnable接口来实现(一)Runnable接口方法run() 使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。(二)实现Runn Thread和Runnable实现线程【例10.2】在applet程序中,通过Runnable接口实现一个可变的时间,程序名为TestRunnable.java,代码如下所示:package bedeck;import java.awt.event.*;import java.applet.*;import java.awt.*;import java.util.*;import java.text.*;public class TestRunnable extends Applet implements RunnableThread clockThread = null;/* *下面是applet程序中的方法进行重画 * */public void init()this.setBackground(Color.black); /设置applet程序的前背景色this.setForeground(Color.yellow); /设置applet程序的前景色public void start()if(clockThread = null)clockThread = new Thread(this,"TestRunnable");clockThread.start(); /启动一个线程/* * 在applet程序中显示当然时间 * */public void paint(Graphics g) Date date = new Date();DateFormat df = DateFormat.getTimeInstance(); /构造一个时间格式化器String str = df.format(date);g.drawString(str, 50, 60); /写时间的内容public void stop()clockThread = null; /结束线程/* * Runnable接口实例化 * */public void run()Thread localThread = Thread.currentThread(); /得到当前线程对localThread进行初始化while(localThread = clockThread)repaint(); tryThread.sleep(1000);catch(InterruptedException e)System.out.println("异常:"+e);说明: 程序中Thread clockThread = null,表明clockThread是一个空线程,没有为它分配系统资源,一个线程需从start方法开始,否则将产生IllegalThreadStateException异常.运行结果如10-2所示10-2 Runnable接口实现线程(三) Thread和Runnable实现线程的比较由继承Thread类创建线程对象简单方便,可以直接操作线程,但不能再继承其他类。在继承其他类时可以Runnable接口创建线程对象。不管用 Threa中完成任务的处理代码d还是Runnable方法,但他们都要在Run()方法10.3线程的状态转换线程在一定条件下,状态会发生变化。线程变化的状态转换图如下: (一)新建状态(New):新创建了一个线程对象。(二)就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。(三).运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种: 等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。 其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期10.4线程的优先级与调度10.4.1线程的优先级尽管从概念上可以说线程能同步运行,但在事实上存在着差别,如果计算机有多个CPU则没有问题,但大部分计算机 都是一个CPU,一个只能运行一个线程,如果有多个线程处于运行状态,需要排队等待CPU资源,此时线程自动获得一个线程的优先级,CPU资源分配是根据“先到先服务”的原则确定的。Java为了使有些线程可以提前得到服务,可给线程设置优主,在单 个CPU上运行多线程队列技术,java虚拟机支持固定优先级队列,一个线程的执行顺序取决于其他对其他Runnable线程的优先级。张程在创建时,继承了父类的优主 先级,线程创建后,可以在任何时刻调用setPriority方法改京戏线程的优主 先级,优先级为110。(一)Thread类定义了基本3个常数Static int MAX_PRIORITY 线程可以具有的最高优先级, 取值为10Static int MIN_PRIORITY线程可以具有的最低优先级, 取值为1。Static int NORM_PRIORITY分配给线程的默认优先级,取值为5(二)线程先优级的使用【例10.2】在线程优先级使用的情况下,程序名为UsePriority.java,代码如下所示:package bedeck;import java.awt.*;import java.awt.event.*;public class UsePriority extends Threadpublic static void main(String a)UsePriority t = new UsePriority4; /用数据创建四个线程/* * 对线程进行初始化 * */for(int i = 0 ; i<t.length ; i+)ti = new UsePriority();/* * 启用线程 * */for(int i = 0 ; i < t.length ; i+)ti.start();System.out.println("i=t"+i);/* * 设置线程的优先级 * */t2.setPriority(MIN_PRIORITY); t3.setPriority(MAX_PRIORITY);public void run()System.out.println("OK");for(int i = 0 ; i < 1000000 ; i+)System.out.println( "n"+getName()+"线程的优先级是"+getPriority()+"已计算完毕");运行结果如10-3所示10-3 线程优先级【注】Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级。多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再新启动。每个线程都有默认的优先级。主线程的默认优先级为10.4.2线程的的状态通过线程方法可以控制线程的状态。(一)挂起一个线程如果要暂停一个线程可使用suspend()方法,在程序运行中可能需要挂起一个一程耍 不指定多少时间。(二)停止一个线程用stop()方法可以停止线程的执行,但需注意的是,这并没有消灭这个线程,只是停止了线程的执行,但这个线程不能用start()进行重新启动(三)线程睡眠Thread.sleep(long millis)方法,使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,就转为就绪(Runnable)状态。sleep()平台移植性好 (四)线程等待Object类中的wait()方法,导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法。这个两个唤醒方法也是Object类中的方法,行为等价于调用 wait(0) 一样。 (五)线程让步Thread.yield() 方法,暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。(六)线程加入join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。 (七)线程唤醒Object类中的notify()方法,唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。 直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。类似的方法还有一个notifyAll(),唤醒在此对象监视器上等待的所有线程。 【注意】线程方法控制是指用Thread类的对象方法来进行控制的,所以请读都撑握好Thread类的方法。附:常见线程名词解释1.主线程JVM调用程序mian()所产生的线程。2.当前线程这个是容易混淆的概念。一般指通过Thread.currentThread()来获取的进程。3.后台线程指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。4.前台线程是指接受后台线程服务的线程,其实前台后台线程是联系在一起,就像傀儡和幕后操纵者一样的关系。傀儡是前台线程、幕后操纵者是后台线程。由前台线程创建的线程默认也是前台线程。可以通过isDaemon()和setDaemon()方法来判断和设置一个线程是否为后台线程。10.5线程的同步前面的线程例子都是独立且异步执行,也就是说每个线程都包含了运行时所需要的数据和方法,也不关心其他线程的状态和行为,但有时一些同时运行的线程需要共享数据,如两个线程同时存取一个数据流,其中一个对数据流修改,而另一个线程使用的仍是原来的数据,这样会使数据不一致,因些,编程时必须考虑其他线程的状态和行为。Java提供了同步设定功能,共享对象可将自己的成员方法定义为同步化(synchronized)方法,通过调用同步化方法来执行单一线程,其他线程则不能同时调用同一个对象的同步方.一个时刻只有一个synchronized方法或代码段被调用wain(long millis,int nanos),notify()/notifyAll(),interrupt,效率/死锁,volatile成员变量。【注意】Wait,notify,notifyAll必须在线程获得对象监视器的所有权否则抛出lllegalMonitorStateException拥有对象的监视器的所有权的时刻在synchronized方法中,在synchronized语句中,在对象类的静态synchronized方法中,ClasName.class。10.6何时使用多线程及注意问题考虑到多线和时,人们立刻会想到某些任务是可以使用多线程的,例如计算、数据库查询,以及输入的获得。因为这些任务通常都被认为是后台任务,不直接与用户打交道。在这些任务中,当然可以使用多线程,那么还有没有其他任务也适合多任务呢?在java语言程序设计中,动态效果的程序都会使用多线程,例如动画的播放、动态文字的字幕等等。没有任何事情是完美的,多线程民不例外,应该清配地意识到在程序中使用多线程是有代价的,它会对系统产生以下影响:线程需要占用内存;线程过多,会消耗大量CPU时间来跟踪线程;必须考虑多线程同时访问共享资源的问题,如果没有协调好,就会产生令人意想不到的问题,例如可怕的死锁和资源竞争;因为同一个任务的所有线程都共享相同的地址并共享任务的全局变量,所以必须考虑多线程同时访问全局变量的问题。10.7小结软件,程序,进程,多任务,线程,多线程的概念和它们的联系,对于这几个概念,通过有下图所示:软件程序程序线程进程进程线程线程实现线程的两种方法:Thread类和Runnable接口,Thread类在类中没继承其它类的情况下使用,而Runnable接口通常本类中继承了其它类时,而有不得不线程的时候使用,但这两个实现线程的方法都得用start()方法启用一个线程,然后自动去调用Run()方法,确定线程实现的内容。10.8习题1.从Thread继承一个类,并重载run()方法。在run()中,打印一条消息,然后调用sleep()。重复三遍以后从run()返回。在构造器中打印一条启动消息,重载finalize()并打印一条结束消息。再写一个线程类,在其run()中调用System.gc()和System.runFinalization(),在调用的时候分别打印消息。为这些线程类创建几个实例,运行它们并观察结果。2.创建一个程序,产生大量Timer对象,在时间到期后让它们执行一些简单的工作,来演示java.util.Timer可以伸缩到很大数目。3.演示类中的同步控制方法可以调用同一个类上的另一个同步控制方法。后者也能调用同一个类上的第三个同步方法。创建一个单独的Thread对象调用并第一个同步控制方法。4.建立两个Thread的子类,一个在run()中启动,然后调用wait(),另一个在run()中捕获第一个线程对象的引用。她应该在过几秒钟后对第一个线程调用notifyAll(),使得第一个线程能打印一条消息。5.写一个“忙等待”的例子。一个线程休眠一段时间然后把一个标志设为真。第二个线程在一个while循环中观察这个标志(这就是“忙等待”),当标志变为真的时候,把这个标志设置为假,并向控制台报告这个变化。注意程序在“忙等待”里花费的时间,然后重写这个程序,这时使用wait()而不是“忙等待”。6.使用wait()和notify()解决一个生产者,一个消费者的问题。生产者不能覆盖消费者的缓冲区,这在生产的速度大于消费的时候有可能发生。如果消费者的速度大于生产者,那么它一定不能把同样的数据读取两遍。不要对生产者和消费者的速度做任何假设。

    注意事项

    本文(第10章 java 多线程编程.doc)为本站会员(asd****56)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开