一 进程与线程
1 进程
一个进程具有独立完备的执行环境,如独立的内存空间,代码段,指令寄存器等。
大多数系统支持进程间通信(Inter Process Communication)资源。IPC往往不仅仅在同一台计算机系统上使用,也往往运用于不同计算机系统之间的通信。
2 线程
线程只存在于进程中,一个进程包含多个线程。比如一个java程序中可以有多个线程存在。
线程不具有独立的内存空间,而是和同进程内的其他线程共享进程的内存空间。
由于线程共享进程的资源,同进程的线程之间往往需要大量的互斥和同步。
二 java线程的创建
1 创建方式
a 生成实现了Runnable接口的实例,并把他传给Thread对象。
b 继承Thread类并实现run方法。
2 线程的状态
a Born(新建)
线程类实例被创建,此时线程已经初始化分配了资源,但是还没有调用start方法。
b Runnable(就绪)
当start方法执行时,线程进入Runnable状态。
此时线程具备可运行条件,进入线程队列。一旦获得CPU使用权,进入Running状态。
c Running(运行)
run方法被调用。
d Blocked(阻塞)
处于Running状态的线程因事件的发生导致让出CPU的使用权,则进入Blocked状态。
处于Blocked状态的线程,必须消除阻塞原因,才能转入Runnable状态。
sleep(睡眠)
yield(重新进入Runnable)
wait(等待)
e Dead(死亡)
线程死亡原因有二:正常运行的线程执行完全部工作,既执行完了run方法。
线程被提前墙纸终止,例如调用destroy方法。
死亡的线程不能被重启,否则IllegalThreadStateException异常。
注意:
在run方法的I/O操作期间,处理器无法从一个线程切换到另外一个线程,及时时使用时间片的调度策略也是如此。我们把这种情况称为线程由于I/O操作而阻塞。
三 锁
每个对象都包含一把锁。
调用任何被声明为同步的方法时,对象就会被锁定,不可调用该对象的任何同步方法。
除非第一个方法完成结束并解除了锁定。
四 使线程Blocked(阻塞)的各种方法
a suspend()、resume() ,interrupt()
1) 通过suspend()函数,可使线程进入停滞状态。通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回可执行状态。
2) 当调用suspend()函数后,线程不会释放它的“锁标志”。
3) 使用interrupt方法中断线程,终止
while(!Thread.currentThread.isInterrupted()&& more work todo){
}
b sleep(睡眠)
1) sleep ()函数有一个参数,通过参数可使线程在指定的时间内进入Blocked状态,当指定的时间过后,线程则自动进入Runnable状态。
2) 当调用sleep ()函数后,线程不会释放它的“锁标志”。
c yield(重新进入Runnable)
相当于sleep(0)
1) 通过yield ()函数,可使线程进入Runnable状态,排程器从可执行状态的线程中重新进行排程。所以调用了yield()的函数也有可能马上被执行。
2) 当调用yield ()函数后,线程不会释放它的“锁标志”。
d wait()、notify()和notifyAll()
1) wait()函数有两种形式:第一种形式接受一个毫秒值,用于在指定时间长度内暂停线程,使线程进入停滞状态。第二种形式为不带参数,代表waite()在notify()或notifyAll()之前会持续停滞。
2) 当对一个对象执行notify()时,会从线程等待池中移走该任意一个线程,并把它放到锁标志等待池中;当对一个对象执行notifyAll()时,会从线程等待池中移走所有该对象的所有线程,并把它们放到锁标志等待池中。
3) 当调用wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。
4) waite()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。
e join
t.join(1000)等待该线程终止的最长时间为1000毫秒。
t.join() = t.join(0)