1、线程休眠 sleep(long time) 单位为毫秒
线程休眠指的是让线程暂缓执行以一下,等到了预计时间之后再恢复执行
sleep方法会让当前线程立即交出CPU,但不会释放对象锁,即使当前持有某个对象的的线程调用sleep方法休眠了,其他线程也无法持有该对象;
public class Test implements Runnable {
private int ticket = 100;
@Override
public void run() {
synchronized (this) {//Runnable对象
while (ticket > 0) {
try {
//sleep不会释放对象锁,即使当前线程休眠了,其他线程也无法拿到该runable对象,当该线程休眠结束后,继续执行;
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "还剩" + ticket-- + "张票");
}
}
}
public static void main(String[] args) {
Runnable runnable = new Test();
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
Thread thread3 = new Thread(runnable);
Thread thread4 = new Thread(runnable);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
因为sleep不会释放对象锁,即使当前线程休眠了,其他线程也无法拿到该runable对象,当该线程休眠结束后,继续执行;所以该结果图:
可见,在Thread-0运行时,调用了sleep,但其他线程无法拿到锁对象;
2、线程让步 yield()
暂停当前正在执行的线程对象,并执行其他线程(只能让拥有相同优先级的线程获取CPU)
当前线程不会立即交出CPU,交出时间由系统调度
同样不会释放对象锁,即使当前持有某个对象的的线程调用yield方法让步了,其他线程也无法持有该对象,等让步结束后,继续该线程的执行;
public class Test2 implements Runnable{
@Override
public synchronized void run() {
for(int i=0;i<5;i++) {
Thread.yield();//不会释放对象锁
System.out.println(Thread.currentThread().getName()+"="+i);
}
}
public static void main(String[] args) {
Runnable runnable=new Test2();
Thread thread1=new Thread(runnable,"线程1");
Thread thread2=new Thread(runnable,"线程2");
Thread thread3=new Thread(runnable,"线程3");
thread1.start();
thread2.start();
thread3.start();
}
}
结果:
因为不会释放对象锁,即使当前持有某个对象的的线程调用yield方法让步了,其他线程也无法持有该对象,等让步结束后,继续该线程的执行;
由图可知:线程1完全执行完毕之后,另一个线程才开始执行;在线程1运行的过程中,在线程中调用了yield方法,线程1让步了,但其他线程拿不到这个对象锁,可见yield不会释放对象锁;
3、线程等待 join()
若一个线程1需要等待另一个线程2执行完毕后再恢复执行,可以在线程1中调用线程2的join()方法 ,会释放对象锁
public class Test2 {
public static void main(String[] args) {
try {
System.out.println("主线程开始");
Runnable runnable=new MySleepTest();
Thread thread1=new Thread(runnable);
thread1.start();
//线程等待,
thread1.join();
System.out.println("主线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4、线程停止
1 设置标志位(无法处理线程阻塞时停止的问题)
class MyStopThread implements Runnable{
//设置标志位
private boolean flag=true;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
int i=0;
while(flag){//flag为true时
System.out.println(Thread.currentThread().getName()+",i="+i);
i++;
}
//标志位flag一旦变为false,就输出该句
System.out.println("线程停止");
}
}
public class Test{
public static void main(String[] args) {
MyStopThread runnable=new MyStopThread();
Thread thread=new Thread(runnable);
thread.start();
//让线程启动1S以后关闭
try {
//让主线程休眠1S
thread.sleep(1000);
//然后使标志位变为false
runnable.setFlag(false);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.调用Thread类提供的stop方法强行关闭线程, 本方法现在已经不推荐使用,因为会产生不完整数
因为是强行关闭,所以可能导致执行到一半就结束了,导致数据变化不一致。
3.调用Thread类提供的interrupt()方法:
A.若线程中没有使用类似sleep、wait、join时,调用此线程对象的interrupt方法并不会真正中断线程,只是简单地将线程的状态置为interrupt而已,我们可以根据此状态来进一步确定如何处理线程
class MyThread implements Runnable {
private boolean flag = true;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
int i = 0;
while (flag) {
boolean bool=Thread.currentThread().isInterrupted();//取得线程的状态
if(bool){
//一旦线程的状态有false变为true,就return结束该线程
System.out.println("线程已被置为中断状态");
return;
}
System.out.println("当前线程状态为:"+bool);
System.out.println(Thread.currentThread().getName() + ",i=" + i);
i++;
}
System.out.println("线程停止");
}
}
public class Test4 {
public static void main(String[] args) {
MyThread runnable=new MyThread();
Thread thread=new Thread(runnable);
thread.start();
try {
Thread.sleep(1000);
thread.interrupt();//若线程中没有使用类似sleep、wait、join时,只是改变线程的状态,改为true
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
B.若线程中调用了阻塞线程的方法,如:sleep(),wait(),join()
此时再调用线程的interrupt方法会抛出异常InterruptedException , 同时将线程状态还原(isInterrupted=false)
class MyTest implements Runnable {
private boolean flag = true;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
int i = 0;
while (flag) {
try {
Thread.sleep(200);
/* boolean bool=Thread.currentThread().isInterrupted();
if(bool){ //可以发现bool一直为false
System.out.println("线程已被置为中断状态");
return;
}
System.out.println("当前线程状态为:"+bool);
System.out.println(Thread.currentThread().getName() + ",i=" + i);
i++;*/
} catch (InterruptedException e) {
//再catch中return,结束
System.out.println("抛出中断异常");
return;//终止
}
}
System.out.println("线程停止");
}
}
public class Test {
public static void main(String[] args) {
MyTest runnable=new MyTest();
Thread thread=new Thread(runnable);
thread.start();
try {
Thread.sleep(1000);//线程休眠
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}