首先,要辨析进程与线程的概念: java
进程是程序执行的过程,它持有资源和线程,相对于程序自己而言具备动态性。 多线程
线程是系统中最小的执行单元,同一个进程中可能有多个线程,它们共享该进程持有的资源。线程的通讯也称为线程的交互,方式主要有互斥和同步。同步是指线程之间经过共同协做完成某项工做,线程间具备次序性;互斥是指线程间对某一资源的竞争,一次只能有一个线程访问该资源。 spa
介绍完了这些基本概念,下面简单介绍一下Java对多线程的支持. 线程
java中经过类Thread和接口Runnable来实现多线程的操做。它们都有一个run方法来指定线程工做时执行的代码。对象
Thread类的经常使用方法blog
类别继承 |
名称接口 |
简介生命周期 |
线程的建立队列 |
Thread() |
|
Thread(String name) |
||
Thread(Runnable target) |
||
Thread(Runnable target, String name) |
||
线程的方法 |
void start() |
启动线程 |
static void sleep(long millis) |
线程休眠 |
|
static void sleep(long millis, int nanos) |
||
void join() |
某线程调用join方法后,使其余线程等待该线程终止 |
|
void join(long millis) |
||
void join(long millis, int nanos) |
||
static void yield() |
当前正在运行的线程马上释放处理器,从新加入竞争处理器的队列 |
|
获取线程引用 |
static Thread currentThread() |
返回当前正在运行的线程的引用 |
使用多线程有两种方式,一种是直接继承Thread类,一种是实现Runnable接口
另外,经过volatile关键字声明的成员变量能够保证当其余线程修改该成员变量后,本线程能够正确读取到此成员变量的值。
请结合OS中进程的5态来思考。如下线程状态和方法的介绍来自DreamSea(张小哲)
Ø线程的方法(Method)、属性(Property)
每一个类都有本身的优先级,通常property用1-10的整数表示,默认优先级是5,优先级最高是10;优先级高的线程并不必定比优先级低的线程执行的机会高,只是执行的机率高;默认一个线程的优先级和建立他的线程优先级相同;
2)Thread.sleep()/sleep(long millis)
当前线程睡眠/millis的时间(millis指定睡眠时间是其最小的不执行时间,由于sleep(millis)休眠到达后,没法保证会被JVM当即调度);sleep()是一个静态方法(static method) ,因此他不会中止其余的线程也处于休眠状态;线程sleep()时不会失去拥有的对象锁。 做用:保持对象锁,让出CPU,调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留必定的时间给其余线程执行的机会;
让出CPU的使用权,给其余线程执行机会、让同等优先权的线程运行(但并不保证当前线程会被JVM再次调度、使该线程从新进入Running状态),若是没有同等优先权的线程,那么yield()方法将不会起做用。
5)object.wait() 当一个线程执行到wait()方法时,他就进入到一个和该对象相关的等待池(Waiting Pool)中,同时失去了对象的机锁—暂时的,wait后还要返还对象锁。当前线程必须拥有当前对象的锁,若是当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常,因此wait()必须在synchronized block中调用。sleep()和wait()方法的最大区别是:sleep()睡眠时,保持对象锁,仍然占有该锁;而wait()睡眠时,释放对象锁。可是wait()和sleep()均可以经过interrupt()方法打断线程的暂停状态,从而使线程马上抛出InterruptedException(但不建议使用该方法)。
唤醒在当前对象等待池中等待的第一个线程/全部线程。notify()/notifyAll()也必须拥有相同对象锁,不然也会抛出IllegalMonitorStateException异常。
非正确中止的方法:stop()
要正确中止线程,应该使用正确的退出标记。正常状况下run方法执行完毕线程就中止了,可是有些状况下run方法中须要while循环保持轮询,因此应该为while循环设置合适的退出条件,即退出标记,保证线程正确中止。
或者使用interrupt()方法的初衷并非要中止线程,正常状况下,调用该方法能够将中断标记设置为TRUE。可是,当某个线程由于调用了wait()或者sleep()等方法而被阻塞时,此时调用interrupt()方法并不能正确的将interrupted标记设置为TRUE,而且同时会抛出中断异常。
争用条件:当多个线程同时共享访问同一个内存数据时,每一个线程都尝试操做该数据,从而致使数据被破坏。
互斥是指在同一时刻只有一个线程能够对临界区进行操做。在JAVA中,能够经过synchronized块或者方法来实现。
在synchronized块中,须要对某个对象进行加锁,并将须要互斥的代码放入synchronized块中,从而来实现互斥行为。得到该锁的进程能够进入该synchronized块中.
而同步则是线程之间的一种通讯机制,经过同步能够规定线程执行的顺序。例如,当线程不知足访问某资源时,能够经过调用锁对象的lock.wait()方法,使该线程让出CPU,让出锁,并在该锁对象的waitset中等待。知足条件时,能够经过lock.notify()方法随机唤醒一条线程,lock.notifyAll()则唤醒该waitset中全部的线程,使它们从新竞争该锁。被唤醒的线程从wait()方法处继续执行。