1.thread.sleep方法
sleep方法使线程休眠,让cpu去执行其他线程。但是并不会释放锁(当前线程如果持有某个对象的锁,在sleep期间不会释放)
代码实例:
/**
* @author cki
* @since 1.0.0, 2017/11/07
*/
public class Test {
private Object object = new Object();
public static void main(String[] args) {
Test versionController = new Test();
MyThread test1 = versionController.new MyThread("张三");
MyThread test2 = versionController.new MyThread("李四");
test1.start();
test2.start();
}
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
synchronized (object) {
try {
System.out.println("线程" + Thread.currentThread().getName() + "进入睡眠状态");
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
}
System.out.println("线程" + Thread.currentThread().getName() + "睡眠结束");
}
}
}
}
运行结果:
从结果中可以看出,在线程thread-0 sleep期间,由于持有了object这个对象的锁,而且没有释放,导致thread-1线程必须等待他执行结束后才能访问object对象
2.thread.yield方法
yield方法也会使当前线程释放cpu,让cpu去执行其他线程,也不会释放锁,与sleep不同的是,yield方法不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。
调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,也就是说调用该方法的线程会与其他线程再一起竞争cpu。
代码示例:
/**
* @author cki
* @since 1.0.0, 2017/11/07
*/
public class Test {
private Object object = new Object();
public static void main(String[] args) {
Test versionController = new Test();
MyThread test1 = versionController.new MyThread("张三");
MyThread test2 = versionController.new MyThread("李四");
test1.start();
test2.start();
}
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(name + " " + i);
if (i == 5) {
this.yield();
}
}
}
}
}
运行结果:
以上两种结果都是有可能的,因为线程1调用yield方法后,会与线程2一起竞争cpu,所以再执行哪个线程是不确定的。
3.thread.join方法
join方法可以使一个线程等待另一个线程执行完再执行或者是等待另一个线程若干时间再执行。join方法可以加入参数,作为等待的时间,而不用等待线程执行完毕。
join()
join(long millis) //参数为毫秒
join方法的底层实际上是调用了object的wait方法,而wait方法会释放对象锁,因此join方法也同理。
/**
* @author cki
* @since 1.0.0, 2017/11/07
*/
public class Test {
private Object object = new Object();
public static void main(String[] args) {
Test versionController = new Test();
System.out.println("线程" + Thread.currentThread().getName() + "开始执行");
MyThread test1 = versionController.new MyThread("张三");
test1.start();
try {
test1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() + "结束执行");
}
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + "开始执行");
try {
this.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() + "结束执行");
}
}
}
当把test1.join()该行注释以后,执行结果如下:
当执行test1.join()后,执行结果如下:
可以看到,main线程会等待thread-0线程执行结束后再执行。
4.thread.interrupt方法
interrupt方法,顾名思义就是中断线程,但是它只可以中断处于阻塞状态的线程,它会使处于阻塞状态的线程抛出InterruptedException异常,同时中断线程。
代码示例如下:
/**
* @author cki
* @since 1.0.0, 2017/11/07
*/
public class Test {
private Object object = new Object();
public static void main(String[] args) {
Test versionController = new Test();
MyThread test1 = versionController.new MyThread();
test1.start();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
test1.interrupt();
}
class MyThread extends Thread {
@Override
public void run() {
try {
this.sleep(5000);
} catch (InterruptedException e) {
System.out.println("线程" + Thread.currentThread().getName() + "被中断");
}
}
}
}
执行结果如下:
可以看到thread-0线程在阻塞过程中抛出了InterruptedException异常。
另一个问题,thread.interrupt可以中断阻塞状态中的线程,那么正在运行中的线程是否可以中断呢,答案是不可以的,对于非阻塞状态的线程,调用interrupt方法仅仅是把中断标志位置为true,并不会抛出异常,因此也不能中断线程。如果需要中断非阻塞状态的线程,需要配合thread.isInterrupted()方法执行。thread.isInterrupted()用于判断中断标志位置是否为true。
代码实例如下:
/**
* @author cki
* @since 1.0.0, 2017/11/07
*/
public class Test {
private Object object = new Object();
public static void main(String[] args) {
Test versionController = new Test();
MyThread test1 = versionController.new MyThread();
test1.start();
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
test1.interrupt();
}
class MyThread extends Thread {
@Override
public void run() {
int i = 0;
do {
System.out.println(i);
i++;
} while (i < Integer.MAX_VALUE && !Thread.currentThread().isInterrupted());
}
}
}
运行结果如下:
可以看到,线程thread-1在执行若干时间后被test1.interrupt()方法和isInterrupted()方法配合执行后中断。
最后附上一张线程状态转换图: