1.线程生命周期
(1)生命周期的五种状态
新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread t1=new Thread();
就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
自然终止:正常运行run()方法后终止
异常终止:调用stop()方法让一个线程终止运行
堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)
2.线程的基本操作
2.1 新建线程
实现Runnable接口,实现Thread类,重写run()
Thread t = new Thread(new TestThread())
t.start()
2.2 终止线程
Thread.stop() --------不推荐,可能会造成数据损坏
安全终止线程
例:
public static class ChangeObjectThread extends Thread{
volatile boolean stopme = false;
public void stopMe(){
stopMe = true;
}
@Override
public void run(){
while(true){
if(stopMe){
break;
}
synchronized(user){
int v = (int) (System.currentTimeMillis() / 1000);
user.setId(v);
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
user.setName(v+"");
}
Thread.yield();
}
}
}
2.3线程中断
public void Thread.interrupt() //中断线程
public boolean Thread.isInterrupted() //判断是否被中断
public static boolean Thread.interrupted() //判断是否被中断,并清除当前中断状态
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(){
@Override
public void run() {
while(true){
if(Thread.currentThread().isInterrupted()){
System.out.println("Interrupted!");
break;
}
System.out.println("-----------");
Thread.yield();
}
}
};
t1.start();
Thread.sleep(2000);
t1.interrupt();
}
2.4 等待(wait)和通知(notify)
wait 和 notify不是在Thread类中而是属于Object类,这意味着任何对象可以调用这两个方法。
线程A中当一个对象实例上调用obj.wait()后,线程会在这个对象上等待,直到其他线程调用了obj.notify()。该线程会进入等待队列,这个队列中
可能有多个线程同时等待某一对象,当obj.notify()被调用时,会从该队列中随机唤醒一个线程。obj.notifyAll(),唤醒该队列全部的等待线程。
在调用wait和notify前必须获得object的监视器,在wait方法执行后会释放监视器,这样的目的是使得其他等待在object对象上的线程不至于因为
线程T1的休眠而全部无法正常执行。线程T2在notify调用前也必须获得object的监视器,唤醒T1并释放监视器,T1被唤醒后第一件事是等待监视器,
当监视器顺利获得后才继续执行后续代码。
public class SimpleWN {
final static Object object = new Object();
public static class T1 extends Thread{
@Override
public void run() {
synchronized(object){
System.out.println(System.currentTimeMillis()+":T1 start!");
try{
System.out.println(System.currentTimeMillis()+"T1 wait for object!");
object.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()+"T1 end!");
}
}
}
public static class T2 extends Thread{
@Override
public void run() {
synchronized(object){
System.out.println(System.currentTimeMillis()+"T2 start! notify one thread");
object.notify();
System.out.println(System.currentTimeMillis()+"T2 end");
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
Thread t1 = new T1();
Thread t2 = new T2();
t1.start();
t2.start();
}
}
2.5 挂起(suspend)和继续执行(resume)线程
public class GoodSuspend {
public static Object u = new Object();
public static class ChangeObjectThread extends Thread{
volatile boolean suspendme = false;
public void suspendMe(){
suspendme = true;
}
public void resumeMe(){
suspendme = false;
synchronized(this){
notify();
}
}
@Override
public void run() {
while(true){
synchronized(this){
while(suspendme){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
synchronized(u){
System.out.println("in ChangeObjectThread");
}
Thread.yield();
}
}
}
public static class ReadObjectThread extends Thread{
@Override
public void run() {
while(true){
synchronized(u){
System.out.println("in ReadObjectThread");
}
Thread.yield();
}
}
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ChangeObjectThread t1 = new ChangeObjectThread();
ReadObjectThread t2 = new ReadObjectThread();
t1.start();
t2.start();
Thread.sleep(1000);
t1.suspendMe();
System.out.println("suspend t1 2 sec");
Thread.sleep(2000);
System.out.println("resume t1");
t1.resumeMe();
}
}
2.6 等待线程结束(join)和谦让(yield)
public class Join {
public volatile static int i = 0;
public static class AddThread extends Thread {
@Override
public void run() {
for(i = 0;i<100000;i++);
}
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
AddThread at = new AddThread();
at.start();
at.join();
System.out.println(i);
}
}
若不使用join等待AddThread,i很可能是0或是一个很小的数,因为AddThread还没开始执行i就已经输出,使用join后,表示主线程愿意等待
AddThread执行完毕,故i总是100000.
yield()执行后当前线程会主动让出cpu,但还会进行cpu争夺战。