什么是多线程编程?多线程编程基础知识

编程语言及工具

99人已加入

描述

  摘要:多线程编程是现代软件技术中很重要的一个环节。要弄懂多线程,这就要牵涉到多进程。本文主要以多线程编程以及多线程编程相关知识而做出的一些结论。

  什么是多线程编程?

  多线程编程技术是Java语言的重要特点。多线程编程的含义是将程序任务分成几个并行的子任务。特别是在网络编程中,你会发现很多功能是可以并发执行的。比如网络传输速度较慢、用户输入速度较慢,你可以用两个独立的线程去完成这两个功能,而不影响正常的显示或其它功能。

  多线程是与单线程比较而言的,普通的Windows采用单线程程序结构,其工作原理是:主程序有一个消息循环,不断从消息队列中读入消息来决定下一步所要干的事情,一般是针对一个函数,只有等这个函数执行完之后,主程序才能接收另外的消息来执行。比如子函数功能是在读一个网络数据,或读一个文件,只有等读完这个数据或文件才能接收下一个消息。在执行这个子函数过程中你什么也不能干。但往往读网络数据和等待用户输入有很多时间处于等待状态,多线程利用这个特点将任务分成多个并发任务后,就可以解决这个问题。

  多线程编程基础知识详解

  一、进程

  1.程序:由源代码生成的可执行应用。(如:QQ.app)

  2.进程:一个正在运行的程序可以看做一个进程。(正在运行的QQ就是一个进程),进程拥有独立运行所需的全部资源。

  3.线程:程序中独立运行的代码段。(如:接收QQ消息的代码块)

  一个进程是由一个和多个线程组成,进程只负责资源的调度和分配,线程才是程序真正的执行单元,负责代码的执行。

  二、单线程

  1、每个正在运行的程序(即进程),至少包含一个线程,这个线程叫主线程。

  2、主线程在程序启动时被创建,用于执行main函数。

  3、只有一个主线程的程序,称作单线程程序。

  4、主线程负责执行程序所有的代码(UI展现以及刷新,网络请求,本地请求)。这些代码只能顺序执行,无法并发执行。

  注意:UI展现和刷新只能写在主线程中。

  三、多线程

  1、拥有多个线程的程序,称作多线程程序。

  2、iOS允许用户自己开辟新的线程,相对于主线程来说,这些线程,称作子线程。

  3、子线程和主线程都是独立运行的单元,各自的执行互不影响,因此能够并发执行。

  补充的多线程的基本知识

  4、iOS默认给主线程分配1M的栈空间,默认给子线程分配512K的栈空间。(分配的字节数必须是4K的整数倍)

  5、分配的空间用来存放线程中为变量开辟的空间,一般情况下足够使用。

  6、与栈空间的使用方式不同,主线程和子线程共用同一块内存空间。

  7、程序入口处默认设置了自动释放池,由主线程负责执行代码。子线程新开辟的内存不在主线程管辖范围内(线程之间互不干扰,相互独立),所以子线程为对象开辟的空间不会自动释放,要手动为子线程添加自动释放池。

  8、短时间内使用静态方法开辟大量内存空间或使用循环使用便利构造器,会造成内存瞬间集聚,程序carsh掉,所以要写@autorelease pool。

  9、多线程的种类

  脱离线程:线程结束后被销毁,子线程可能是脱离线程。

  四、单、多线程的区别

  单线程程序:只有一个线程,代码顺序执行,容易出现代码阻塞(页面假死)

  多线程程序:有多个线程,线程之间独立运行,能有效的避免代码阻塞,并且提高程序的运行性能。

  五、JVM与多线程

  Java编写的程序都运行在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是通过线程来实现的。

  每用java命令启动一个java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程 序代码的运行都是以线程来运行的。JVM找到程序程序的入口点main(),然后运行main()方法,这样就产生了一个线程,这个线程称之为主线程。当 main方法结束后,主线程运行完成。JVM进程也随即退出。

  操作系统将进程线程进行管理,轮流(没有固定的顺序)分配每个进程很短的一段时间(不一定是均分),然后在每个进程内部,程序代码自己处理该进程内部线程的时间分配,多个线程之间相互的切换去执行,这个切换时间也是非常短的。

  六、Java语言对多线程的支持

  Java语言对多线程的支持通过类Thread和接口Runnable来实现。这里就不多说了。这里重点强调两个地方:

  // 主线程其它代码段

  ThreadClass subThread = new ThreadClass(); subThread.start(); // 主线程其它代码段 subThread.sleep(1000);

  非脱离线程:线程结束后被挂起,等待唤醒,不销毁。主线程一定是非脱离线程。

  10、iOS中实现多线程的方法

  a、NSObject

  b、NSThread

  c、NSOperation和NSOperationQueue结合使用

  d、GCD(最重要的)

  有人认为以下的代码在调用start()方法后,肯定是先启动子线程,然后主线程继续执行。在调用sleep()方法后CPU什么都不做,就在那里等待休眠的时间结束。实际上这种理解是错误的。因为:

  ①start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。

  ②Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会(也就是靠内部自己协调)。

  七、线程的状态切换

  1、新建状态(New):新创建了一个线程对象。

  2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

  3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

  4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

  ①等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。 ②同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM把该线程放入锁池③其他阻塞:运行的线程执行sleep()或 join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处 理完毕时,线程重新转入就绪状态。

  5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

  八、为什么要多线程编程

  为什么要多线程编程呢?这其中的原因很多,我们可以举例解决

  1)有的是为了提高运行的速度,比如多核cpu下的多线程

  2)有的是为了提高资源的利用率,比如在网络环境下下载资源时,时延常常很高,我们可以通过不同的thread从不同的地方获取资源,这样可以提高效率

  3)有的为了提供更好的服务,比如说是服务器

  4)其他需要多线程编程的地方等等

  九、Java的线程模型

  由于Java是纯面向对象语言,因此,Java的线程模型也是面向对象的。Java通过Thread类将线程所必须的功能都封装了起来。要想建立一个线 程,必须要有一个线程执行函数,这个线程执行函数对应Thread类的run方法。Thread类还有一个start方法,这个方法负责建立线程,相当于 调用Windows的 建立线程函数CreateThread.当调用start方法后,如果线程建立成功,并自动调用Thread类的run方法。因此,任何继承Thread 的Java类都可以通过Thread类的start方法来建立线程。如果想运行自己的线程执行函数,那就要覆盖Thread类的run方法。

  在Java的线程模型中除了Thread类,还有一个标识某个Java类是否可作为线程类的接口Runnable,这个接口只有一个抽象方法run,也就 是Java线程模型的线程执行函数。因此,一个线程类的唯一标准就是这个类是否实现了Runnable接口的run方法,也就是说,拥有线程执行函数的类 就是线程类。 从上面可以看出,在Java中建立线程有两种方法,一种是继承Thread类,另一种是实现Runnable接口,并通过Thread和实现 Runnable的类来建立线程,其实这两种方法从本质上说是一种方法,即都是通过Thread类来建立线程,并运行run方法的。但它们的大区别是通过 继承Thread类来建立线程,虽然在实现起来更容易,但由于Java不支持多继承,因此,这个线程类如果继承了Thread,就不能再继承其他的类了, 因此,Java线程模型提供了通过实现Runnable接口的方法来建立线程,这样线程类可以在必要的时候继承和业务有关的类,而不是Thread类。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分