关于线程状态,网上也是众说风云,以下说到的六种状态来自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
}
}