1.线程的状态:new(创建)->runnable(就绪)->running(运行),运行时又分状态:阻塞(blocked),time waiting(睡眠或等待一定的事件),waiting(等待被唤醒)。
线程执行完毕,或者突然中断,进入dead(死亡or销毁)状态。如下图所示:
2.Thread之sleep()方法:
1)sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。
2)sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。
例子如下:
public class Threadsleep {
private int i = 10;
private Object object = new Object();
public static void main(String[] args) throws IOException {
Threadsleep threadsleep = new Threadsleep();
//下面两个线程共享threadsleep对象
MyThread thread1 = threadsleep.new MyThread();
MyThread thread2 = threadsleep.new MyThread();
thread1.start();
thread2.start();
}
class MyThread extends Thread{
@Override
public void run() {
synchronized (object) {
i++;
System.out.println("i:"+i);
try {
System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
i++;
System.out.println("i:"+i);
}
}
}
}
结果:
结论:当Thread-0进入睡眠状态之后,Thread-1并没有去执行具体的任务。只有当Thread-0执行完之后,此时Thread-0释放了对象锁,Thread-1才开始执行。
3.Thread之join()方法:
join()
join(long millis) //参数为毫秒
join(long millis,int nanoseconds) //第一参数为毫秒,第二个参数为纳秒
1)假如在main线程中,调用thread.join方法,则main方法会等待thread线程执行完毕或者等待一定的时间。
2)如果调用的是无参join方法,则等待thread执行完毕,如果调用的是指定了时间参数的join方法,则等待一定的事件。
例子如下:
public class Threadjoin {
public static void main(String[] args) throws IOException {
System.out.println("进入线程"+Thread.currentThread().getName());
Threadjoin threadjoin = new Threadjoin();
MyThread thread1 = threadjoin.new MyThread();
thread1.start();
try {
System.out.println("线程"+Thread.currentThread().getName()+"等待");
thread1.join();
System.out.println("线程"+Thread.currentThread().getName()+"继续执行");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class MyThread extends Thread{
@Override
public void run() {
System.out.println("进入线程"+Thread.currentThread().getName());
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println("线程"+Thread.currentThread().getName()+"执行完毕");
}
}
}
结果:
结论:1)当调用thread1.join()方法后,main线程会进入等待。然后等待thread1执行完之后再继续执行。
2)thread1.join()后让main线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。
4.Thread之interrupt方法:
1)interrupt,顾名思义,即中断的意思。
2)单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常,也就说,它可以用来中断一个正处于阻塞状态的线程。
例子如下:
public class Threadinterrupt {
public static void main(String[] args) throws IOException {
Threadinterrupt threadinterrupt = new Threadinterrupt();
MyThread thread = threadinterrupt.new MyThread();
thread.start();
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
}
thread.interrupt();
}
class MyThread extends Thread{
@Override
public void run() {
try {
System.out.println("进入睡眠状态");
Thread.currentThread().sleep(10000);
System.out.println("睡眠完毕");
} catch (InterruptedException e) {
System.out.println("得到中断异常");
}
System.out.println("run方法执行完毕");
}
}
}
结果:
结论:1)interrupt方法可以中断处于阻塞状态的线程。
问题:interrupt能不能中断处于非阻塞状态的线程呢?如下例子:
public class Threadinterrupt2 {
public static void main(String[] args) throws IOException {
Threadinterrupt2 threadinterrupt2 = new Threadinterrupt2();
MyThread thread = threadinterrupt2.new MyThread();
thread.start();
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
}
thread.interrupt();
}
class MyThread extends Thread{
@Override
public void run() {
int i = 0;
while(i<Integer.MAX_VALUE){
System.out.println(i+" while循环");
i++;
}
}
}
}
结论:通过测试结果,
发现直接调用interrupt方法不能中断正在运行中的线程。
问题:如何中断正在运行的线程呢?
1)一般会在MyThread类中增加一个属性 isStop来标志是否结束while循环,然后再在while循环中判断isStop的值。如下:
class MyThread extends Thread{
private volatile boolean isStop = false;
@Override
public void run() {
int i = 0;
while(!isStop){
i++;
}
}
public void setStop(boolean stop){
this.isStop = stop;
}
}
那么就可以在外面通过调用setStop方法来终止while循环。
5.Thread其他方法:
1)getId 用来得到线程ID。
2)getName和setName。用来得到或者设置线程名称。
3)getPriority和setPriority。用来获取和设置线程优先级。
4)setDaemon和isDaemon。用来设置线程是否成为守护线程和判断线程是否是守护线程。
5)currentThread()。常用,用来获取当前线程。
演示关系图如下: