多线程编程(1)

  通常,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个Word就启动了一个Word进程。大多时候一个进程需要同时干很多件事情,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。即一个程序至少有一个进程,一个进程至少有一个线程

  我们大学学操作系统的时候,都知道进程是资源分配的基本单位,线程是执行和调度的基本单位,线程本身不拥有资源,资源来自于它的进程。也就是说,进程在执行过程中有自己独立的内存空间,与其他进程相互隔离,因此进程间的通信需要另辟蹊径,比如常见的有管道通信、消息队列、信号量以及套接字等方法,同时,一个进程中有三大块——进程控制块(PCB)、数据段、代码段,这会导致进程间的会产生很大的开销。而线程与线程之间因为共享进程申请的内存区域,它们之间可以相互通信,因为线程的粒度小,使得线程的切换速度比进程快很多,可以极大地提高程序的运行效率,如下,是线程和进程的关系(图片摘自知乎)。

多线程编程(1)

多线程编程(1)

  线程分为两种:用户线程和守护线程。守护 线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。守护线程是用来服务用户线程的,一旦用户线程全部运行结束,程序会终止,守护线程也会随之退出。

  在进入多线程之前,可以先看看线程的几种状态:

1. 新建(NEW):新创建了一个线程对象。

2. 就绪(RUNNABLE或READY) :线程正在参与竞争CPU的使用权。

3. 运行(RUNNING):线程取到了CPU的使用权,正在执行。

4. 阻塞(BLOCKED):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到满足条件(比如超时等待、唤醒)时,该线程重新回到就绪态,参与竞争CPU使用权。

5. 等待(WAITING):线程无限等待某个对象的锁,或等待另一个线程结束的状态。

6. 计时等待(TIME_WAITING):线程在某一段时间内等待某个对象的“锁”,或者主动休眠,亦或者等待一个线程结束,除非被中断,时间一到,马上回到就绪状态,被中断的方法则抛出异常。

7. 终止(Terminated):即线程终止(线程的的代码被执行完毕)和执行过程出现异常或者被外界强制中断。

状态的转换的具体转换如下图所示:

多线程编程(1)

多线程编程(1)

2. Thread类和Runnable接口

  通过继承Thread类,实run方法即可实现一个线程类,常用的API如下:

  方法描述
start()   从新建状态转化为就绪状态,开始参与CPU使用权的竞争。  
run()   直接调用该 Runnable 对象的 run 方法时直接取得CPU的使用权  
interrupt()   中断线程。在程序代码中搭配while (!Thread.interrupted()){..}使用。  
isDaemon()   判断当前线程是否是守护线程。  
setDaemon(boolean true)   将当前线程设置为守护线程,必须在调用start()之后才有效。  
setPriority(int priority)   更改线程的优先级。  
interrupt()   中断线程。  
isAlive()   测试线程是否处于活动状态。  
join(long millisec)   等待该线程终止的时间最长为 millis 毫秒。  
Thread.yield()   暂停当前正在执行的线程对象(让出当前线程的CPU,转为就绪状态),并执行其他线程。  
Thread.currentThread()   返回对当前正在执行的线程对象的引用。  
Thread.sleep(long millisec)   在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zysdfx.html