线程的生命周期
一个线程对象在它的生命周期内,需要经历5个状态。
1. 新生状态(New): 用new关键字建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态。
2. 就绪状态(Runnable): 处于就绪状态的线程已经具备了运行条件,但是还没有被分配到CPU,处于“线程就绪队列”,等待系统为其分配CPU。就绪状态并不是执行状态,当系统选定一个等待执行的Thread对象后,它就会进入执行状态。一旦获得CPU,线程就进入运行状态并自动调用自己的run方法。有4中原因会导致线程进入就绪状态:
1. 新建线程:调用start()方法,进入就绪状态;
2. 阻塞线程:阻塞解除,进入就绪状态;
3. 运行线程:调用yield()方法,直接进入就绪状态;
4. 运行线程:JVM将CPU资源从本线程切换到其他线程。
3. 运行状态(Running):在运行状态的线程执行自己run方法中的代码,直到调用其他方法而终止或等待某资源而阻塞或完成任务而死亡。如果在给定的时间片内没有执行结束,就会被系统给换下来回到就绪状态。也可能由于某些“导致阻塞的事件”而进入阻塞状态。
4. 阻塞状态(Blocked):阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)。有4种原因会导致阻塞:
1. 执行sleep(int millsecond)方法,使当前线程休眠,进入阻塞状态。当指定的时间到了后,线程进入就绪状态。
2. 执行wait()方法,使当前线程进入阻塞状态。当使用nofity()方法唤醒这个线程后,它进入就绪状态。
3. 线程运行时,某个操作进入阻塞状态,比如执行IO流操作(read()/write()方法本身就是阻塞的方法。只有当引起该操作阻塞的原因消失后,线程进入就绪状态。
4. join()线程联合: 当某个线程等待另一个线程执行结束后,才能继续执行时,使用join()方法。
5. 死亡状态(Terminated): 死亡状态是线程生命周期中的最后一个阶段。线程死亡的原因有两个。一个是正常运行的线程完成了它run()方法内的全部工作; 另一个是线程被强制终止,如通过执行stop()或destroy()方法来终止一个线程(注:stop()/destroy()方法已经被JDK废弃,不推荐使用)。当一个线程进入死亡状态以后,就不能再回到其它状态了。
终止线程
* 1. 线程正常执行完毕--》次数
* 2. 外部干涉--》加入标识
* 不要使用stop destroy
/**
* 终止线程
* 1. 线程正常执行完毕--》次数
* 2. 外部干涉--》加入标识
* 不要使用stop destroy
* @author Administrator
*
*/
public class TerminateThread implements Runnable{
//1. 加入标识 标记线程体是否可以运行
private boolean flag=true;
private String name;
public TerminateThread(String name) {
this.name = name;
}
@Override
public void run() {
int i=0;
//2.关联标识, true-->运行 false-->停止
while(flag) {
System.out.println(name+"---->"+i++);
}
}
//3.对外提供方法改变标识
public void terminate() {
this.flag=false;
}
public static void main(String[] args) {
TerminateThread tt=new TerminateThread("止兮");
new Thread(tt).start();
for(int i=0;i<=99;i++) {
if(i==88) {
tt.terminate();//线程的终止
System.out.println("tt game over");
}
System.out.println("main-->"+i);
}
}
}
sleep模拟网络延时、倒计时
sleep模拟网络延时,放大了发生问题的可能性
/**
* sleep模拟网络延时,放大了发生问题的可能性
* @author Administrator
*
*/
public class BlockedSleep01 implements Runnable{
//票数
private int ticketNums=99;
@Override
public void run() {
while(true) {
if(ticketNums<0) {
break;
}
//模拟延时
try {
Thread.sleep(200); //相当于网络延时问题。会造成数据的不准确性
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"--->"+ticketNums--);
}
// TODO Auto-generated method stub
}
public static void main(String[] args) {
//一份资源
BlockedSleep01 web=new BlockedSleep01();
System.out.println(Thread.currentThread().getName());
//多个代理
new Thread(web,"马畜").start();
new Thread(web,"码农").start();
new Thread(web,"码蝗").start();
}
}
sleep 模拟休息
//sleep 模拟休息
public class BlockedSleep02 implements Runnable{
private String winner; //胜利者
@Override
public void run() {
for(int steps=1;steps<=100;steps++) {
//模拟兔子休息
if(Thread.currentThread().getName().equals("rabbit")&&steps%10==0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"--->"+steps);
//比赛是否结束
boolean flag=gameOver(steps);
if(flag) {
break;
}
}
}
private boolean gameOver(int steps) {
if(winner!=null) {//存在胜利者
return true;
}else {
if(steps==100) {
winner=Thread.currentThread().getName();
System.out.println("winner==>"+winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
BlockedSleep02 BlockedSleep02=new BlockedSleep02();
new Thread(BlockedSleep02,"tortoise").start();
new Thread(BlockedSleep02,"rabbit").start();
}
}
sleep 模拟倒计时
/**
* sleep 模拟倒计时
* @author Administrator
*
*/
public class BlockedSleep03 {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// 倒数10个数,一秒一个
int num=10;
while(true) {
Thread.sleep(1000);
System.out.println(num--);
if(num<0) {
break;
}
}
}
}
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* sleep 模拟倒计时
* @author Administrator
*
*/
public class BlockedSleep03 {
public static void main(String[] args) throws InterruptedException {
//倒计时
Date endTime=new Date(System.currentTimeMillis()+1000*10); //倒计时10秒
long end=endTime.getTime();
while(true) {
System.out.println(new SimpleDateFormat("mm:ss").format(endTime));
Thread.sleep(1000);
endTime=new Date(endTime.getTime()-1000);
if(end-10000>endTime.getTime()) {
break;
}
}
}
public static void test() throws InterruptedException {
// 倒数10个数,一秒一个
int num=10;
while(true) {
Thread.sleep(1000);
System.out.println(num--);
if(num<0) {
break;
}
}
}
}
yield 礼让线程,暂停线程 直接进入就绪状态 而不是进入阻塞状态
/**
* yield 礼让线程,暂停线程 直接进入就绪状态 而不是进入阻塞状态
* @author Administrator
*
*/
public class YieldDemo01 {
public static void main(String[] args) {
MyYield my=new MyYield();
new Thread(my,"a").start();
new Thread(my,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->start");
Thread.yield(); //礼让 从运行态到就绪态
System.out.println(Thread.currentThread().getName()+"-->end");
}
}
public class YieldDemo02 {
public static void main(String[] args) {
new Thread(()->{
for(int i=0;i<100;i++) {
System.out.println("lambda……"+i);
}
}) .start();
for(int i=0;i<100;i++) {
if(i%20==0) {
Thread.yield(); //main线程礼让
}
System.out.println("main....."+i);
}
}
}
join:合并线程 插队线程
/**
* join:合并线程 插队线程
* @author Administrator
*
*/
public class BlockedJoin01 {
public static void main(String[] args) throws InterruptedException {
Thread t= new Thread(()->{
for(int i=0;i<100;i++) {
System.out.println("lambda……"+i);
}
});
t.start();
for(int i=0;i<100;i++) {
if(i==20) {
t.join(); //插队 main主线程被阻塞了
}
System.out.println("main....."+i);
}
}
}