线程状态之间的转换

关于线程状态,网上也是众说风云,以下说到的六种状态来自jdk1.8帮助文档,线程随时可处于以下状态之一:

  • NEW
    尚未启动的线程处于此状态。
  • RUNNABLE
    在Java虚拟机中执行的线程处于此状态。
  • BLOCKED
    被阻塞等待监视器锁定的线程处于此状态。
  • WAITING
    正在等待另一个线程执行特定动作的线程处于此状态。
  • TIMED_WAITING
    正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
  • TERMINATED
    已退出的线程处于此状态。
    先放一张大图,说明线程之间的关系(此图拆分了以上六种状态)
    在这里插入图片描述
    下面描述此图中用到的方法:
  • start
    start方法用于启动线程,任何一个线程必须调用start()方法才可以启动,start方法内部自动调用run方法来执行任务。此时线程准备获得cpu的任务分片.
    Runnable :cpu准备获得任务分片,但是还没有获得任务分片。
    Running :cpu获得任务分片。
    注意:一个线程对象,多次调用start方法,会出异常!
    - run
    run方法用来执行任务,任何一个线程必须调用start()方法来启动在线程,在start方法内部会自动调用run方法来执行任务。
    Running :cpu获得任务分片,开始执行任务。
    注意:线程对象直接调用run()方法,不调用start()方法,会在主线程中调用run()中的任务,而不会启动新线程。
    - yield
    yield方法用于将正在运行的进程暂存,让别的进程有机会进入执行。
    举例:
public static void main(String[] args) {
	new Thread(new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			play();
		}
	}).start();
	new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				play();
			}
		}).start();
	play();
}
public static void play() {
	for(int i=0;i<100;i++) {
		System.out.println(Thread.currentThread().getId()+"----"+i);
		Thread.yield();//注释掉可能其他线程无法抢入

	}
}

- wait
wait方法用来让正在执行中的线程进入等待状态,此时不占用cpu。
例如:

	public static void main(String[] args) {
		
		Object obj = new Object();
		
	Thread myThread = new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<20;i++) {
					System.out.println(Thread.currentThread().getId() + "---" + i);
					try {
						Thread.sleep(200);
					} catch (Exception e) {
					}
					if(i==10) {
						try {
							synchronized(obj) {
								obj.wait();	   //先给任意对象加锁,然后调用wait()方法,阻塞当前线程
							}								
						} catch (Exception e) {
						}
						
					}
				}
				
			}
		});
		myThread.start();
		System.out.println("主线程结束 。。。" + Thread.currentThread().getId());//
	}

执行结果

主线程结束 。。。1
10---0
10---1
10---2
10---3
10---4
10---5
10---6
10---7
10---8
10---9
10---10

注意:使用wait()方法必须先将当前对象锁起来,阻塞当前线程。
- notify
notify方法用来将指定线程唤醒

	public static void main(String[] args) {
		
		Object obj = new Object();
		
	Thread myThread = new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<20;i++) {
					System.out.println(Thread.currentThread().getId() + "---" + i);
					try {
						Thread.sleep(200);
					} catch (Exception e) {
					}
					if(i==10) {
						try {
							synchronized(obj) {
								obj.wait();	   //先给任意对象加锁,然后调用wait()方法,阻塞当前线程
								System.out.println("接收到nofify通知");
							}								
						} catch (Exception e) {
						}
						
					}
				}
				
			}
		});
		myThread.start();
		
		try {
			Thread.sleep(5000);
		} catch (Exception e) {
		}
		System.out.println("发出nofify通知");
		synchronized (obj) {
			obj.notify();
		}
		
		
		System.out.println("主线程结束 。。。" + Thread.currentThread().getId());
	}

执行结果

10---0
10---1
10---2
10---3
10---4
10---5
10---6
10---7
10---8
10---9
10---10
发出nofify通知
接收到nofify通知
主线程结束 。。。1
10---11
10---12
10---13
10---14
10---15
10---16
10---17
10---18
10---19

- notiflAll
notiflAll方法用于唤醒正在等待对象监视器的所有线程
例如:

	public static void main(String[] args) {
		
		Object obj = new Object();
		
	Thread myThread = new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<20;i++) {
					System.out.println(Thread.currentThread().getId() + "---" + i);
					try {
						Thread.sleep(200);
					} catch (Exception e) {
					}
					if(i==10) {
						try {
							synchronized(obj) {
								obj.wait();	   //先给任意对象加锁,然后调用wait()方法,阻塞当前线程
							//	System.out.println("接收到nofify通知");
							}								
						} catch (Exception e) {
						}
						
					}
				}
				
			}
		});
		myThread.start();
		
		try {
			Thread.sleep(5000);
		} catch (Exception e) {
		}
		System.out.println("发出nofifyall通知");
		synchronized (obj) {
			obj.notifyAll();
		}
		
		
		System.out.println("主线程结束 。。。" + Thread.currentThread().getId());
	}

执行结果:

10---0
10---1
10---2
10---3
10---4
10---5
10---6
10---7
10---8
10---9
10---10
发出nofify通知
10---11
主线程结束 。。。1
10---12
10---13
10---14
10---15
10---16
10---17
10---18
10---19

注意:使用notify()和notifyAll()方法必须先将当前对象锁起来
- join
join方法将线程之间的并行执行变为串行执行。占用cpu
例如:

class ThreadA  extends Thread{
	
	public void run() {
		for(int i=0;i<20;i++) {
			System.out.println(Thread.currentThread().getId()+"aa----"+i);
			try {
				Thread.sleep(200);
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}
}
class ThreadB extends Thread{
	private ThreadA ta;
	public ThreadB(ThreadA ta) {
		this.ta=ta;
	}
	public void run() {
		for(int i=0;i<20;i++) {
			System.out.println(Thread.currentThread().getId()+"bb---"+i);
			try {
				if(i==10) {
					System.out.println("----线程aa加入线程bb---");
					ta.join();
				}
				Thread.sleep(20);
				} catch (Exception e) {
					// TODO: handle exception
				}
		
		}
	}
}
public static void main(String[] args) {
	ThreadA threada=new ThreadA();
	ThreadB threadb=new ThreadB(threada);
	threada.start();
	threadb.start();
}

执行结果:

10aa----0
11bb---0
11bb---1
11bb---2
11bb---3
11bb---4
11bb---5
11bb---6
11bb---7
11bb---8
11bb---9
10aa----1
11bb---10
----线程aa加入线程bb---
10aa----2
10aa----3
10aa----4
10aa----5
10aa----6
10aa----7
10aa----8
10aa----9
10aa----10
10aa----11
10aa----12
10aa----13
10aa----14
10aa----15
10aa----16
10aa----17
10aa----18
10aa----19
11bb---11
11bb---12
11bb---13
11bb---14
11bb---15
11bb---16
11bb---17
11bb---18
11bb---19

- sleep
sleep()方法是将当前线程暂停多好毫秒后继续执行。此时,线程放弃cpu但是没有放弃锁

public static void main(String[] args) {
	Object obj=new Object();
	Thread myThread=new Thread(new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			for(int i=0;i<100;i++) {
				System.out.println(Thread.currentThread().getId()+"----"+i);
				if(i==20) {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		
	});
	myThread.start();
}

此外,还有一些方法:

  • Interrupt()
    Interrupt()方法用来中断线程.
    例一:
class  myThread2 extends Thread{
	public void run() {
		while(true) {
			try {
				Thread.sleep(300);
			} catch (Exception e) {
				// TODO: handle exception
			break;
			}
			System.out.println(Thread.currentThread().getId());
		}
	}
}
public static void main(String[] args) {
	myThread2 mythread2=new myThread2();
	mythread2.start();
	try {
		Thread.sleep(3000);
		mythread2.interrupt();//发出中断指令
	} catch (Exception e) {
		// TODO: handle exception
	}
}

例二:

class MyThread3 extends Thread{	
	
	public void run() {
	if(!this.isInterrupted())//如果不是中断
			System.out.println(Thread.currentThread().getId() );			
	}	
}
public static void main(String[] args) {
	MyThread3 mythread3=new MyThread3();
	mythread3.start();
	try {
		Thread.sleep(2000);
		mythread3.interrupt();//中断指令
	} catch (Exception e) {
		// TODO: handle exception
	}
}
  • Priority()
    Priority用来设置线程的优先级
    例如:
public static void main(String[] args) {
	System.out.println("主线程的最小优先级:"+Thread.MIN_PRIORITY);
	System.out.println("主线程的最大优先级:"+Thread.MAX_PRIORITY);
	System.out.println("主线程的正常优先级:"+Thread.NORM_PRIORITY);
	Thread myThread=new Thread(new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}	
	});
	myThread.setPriority(6);//更改线程的优先级
	System.out.println("次线程的最小优先级:"+myThread.MIN_PRIORITY);
	System.out.println("次线程的最大优先级:"+myThread.MAX_PRIORITY);
	System.out.println("次线程的正常优先级:"+myThread.NORM_PRIORITY);
	System.out.println(Thread.currentThread().getId()+"次线程的此刻的优先级"+myThread.getPriority());//myThread.getPriority()返回此线程的优先级 
	myThread.start();

}

注意: 当设置线程的优先级是=时, 如果优先级不在 MIN_PRIORITY到 MAX_PRIORITY之间,会报出IllegalArgumentException异常

  • Daemon线程
    Daemon线程主要用于执行辅助性工作,总是最后一个结束
    例如:
class myDamon extends Thread{
	public void run() {
		while (true) {
			int rand=(int)(Math.random()*100);
			System.out.println(Thread.currentThread().getId()+"Daemon---"+rand);
			try {
				Thread.sleep(200);
			} catch (Exception e) {
				// TODO: handle exception
			}
			
		}
	}
}
public static void main(String[] args) {
		myDamon demo=new myDamon();
		demo.setDaemon(true);//Daemon线程主要用于执行辅助性工作,最后一个结束
		demo.start();
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i=0;i<100;i++) {
					int rand=(int)Math.random()*100;
					System.out.println(Thread.currentThread().getId()+"---"+rand);
					try {
						Thread.sleep(200);
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
			}
		}).start();
		System.out.println("主线程结束");
	}

线程的停止:
stop方法已经弃用,所以我们用以下这种方法来停止线程

class myThread extends Thread{
	private boolean isRun=true;
	
	public boolean isRun() {
		return isRun;
	}

	public void setRun(boolean isRun) {
		this.isRun = isRun;
	}

	public void run() {
		while(isRun) {
			try {
				Thread.sleep(2000);
			} catch (Exception e) {
				// TODO: handle exception
			}
			System.out.println(Thread.currentThread().getId());
		}
	}
}

public static void main(String[] args) {
	myThread mythread= new myThread();
	mythread.start();
	try {
		Thread.sleep(5000);
		mythread.setRun(false);
	} catch (Exception e) {
		// TODO: handle exception
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值