多线程学习笔记(七)之wait与sleep的区别、线程停止及守护线程等
来源:互联网 发布:购买淘宝小号 编辑:程序博客网 时间:2024/05/18 15:06
wait()方法与sleep()方法的区别
wait()方法与sleep()方法的区别:
- wait可以指定时间也可以不指定时间;sleep必须指定时间
- 在同步中时,对cpu的执行权和锁的处理不同:
wait:释放cpu执行权,释放锁
sleep:释放cpu执行权,不释放锁
停止线程
定义循环结束标记
因为线程运行代码一般都是循环,只要控制了循环即可。
例如通过flag的方式:
class StopThread implements Runnable{ private boolean flag = true; public void run(){ while (flag){ System.out.println(Thread.currentThread().getName()+"......"); } } public void setFlag(){ flag = false; }}public class StopThreadDemo { public static void main(String[] args){ StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.start(); int num = 1; for (;;){ if (++num==50){ st.setFlag(); break; } System.out.println("main..."+num); } System.out.println("over"); }}
但是上述通过flag的方式有时候也不能使线程停止,例如我们修改下StopThread类的代码:
class StopThread implements Runnable{ private boolean flag = true; public synchronized void run(){ while (flag){ try{ wait(); }catch (InterruptedException e){ System.out.println(Thread.currentThread().getName()+"......"+e); } System.out.println(Thread.currentThread().getName()+"......"); } } public void setFlag(){ flag = false; }}
当线程Thread0获得执行权时,由于wait陷入等待状态,之后当Thread1获得执行权时,由于wait陷入等待状态,此时主线程执行结束,flag设置为false,但是却无法停止线程Thread0与Thread1,两者一直处于等待状态。也就是说,如果线程处于冻结状态(sleep时间很长的时候也是同理),无法读取标记,那么如何使这种情况的线程结束?下面的方式就可以解决这种问题。
使用interrupt(中断)方法
该方法是结束线程的冻结状态,使线程回到运行状态中来。
(注:stop方法已经过时不再使用)
public void interrupt():中断线程
如果线程在调用Object类的wait(),wait(long)或wait(long,int)方法,或者该类的join(),join(long),join(long,int),sleep(long)或sleep(long,int)方法过程中受阻,则其中断状态将被清除(中断状态指程序冻结,即停止运行),它还将收到一个InterruptedException。即interrupt方法可以不等到sleep时间到即可以把其唤醒,是强制性的,因此是在程序应该等待的时候使其中断,会抛出InterruptedException异常。
因此对上述程序进行修改:
class StopThread implements Runnable{ private boolean flag = true; public synchronized void run(){ while (flag){ try{ wait(); }catch (InterruptedException e){ System.out.println(Thread.currentThread().getName()+"......"+e); flag = false; } System.out.println(Thread.currentThread().getName()+"......"); } } public void setFlag(){ flag = false; }}public class StopThreadDemo { public static void main(String[] args){ StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.start(); int num = 1; for (;;){ if (++num==50){ t1.interrupt(); t2.interrupt(); break; } System.out.println("main..."+num); } System.out.println("over"); }}
运行结果:
t1.interrupt()与t2.interrupt()将线程从冻结状态中强制恢复到运行状态中来,让线程具备cpu的执行资格,但是会发生异常InterruptedException,因此原本处于try块中等待的线程t0与t1再interrupt方法之后抛出异常,进入catch块,通过在catch块中将flag置为false使其跳出while循环,最终达到停止线程的目的。
interrupt()只是改变中断状态而已
interrupt()不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。
如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就将得到异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态。
wait() & interrupt()
线程A调用了wait()进入了等待状态,也可以用interrupt()取消.
不过这时候要小心锁定的问题.线程在进入等待区,会把锁定解除,当对等待中的线程调用interrupt()时(注意是等待的线程调用其自己的interrupt(),例如上述demo中的t1与t2调用各自的interrupt方法),会先重新获取锁定,再抛出异常.在获取锁定之前,是无法抛出异常的.
守护线程
void setDaemon(boolean on):将该线程标记为守护线程(后台线程)或者用户线程。当正在运行的线程都是守护线程时,Java虚拟机退出。该方法必须在启动线程前调用。
参数:on——如果为true,则将该线程标记为守护线程。
例如仍是上面的例子的main方法修改下:
public class StopThreadDemo { public static void main(String[] args){ StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.setDaemon(true); t2.start(); int num = 1; for (;;){ if (++num==50){ t1.interrupt(); //t2.interrupt(); break; } System.out.println("main..."+num); } System.out.println("over"); }}
虽然没有使用t2.interrupt(),但是由于将线程t2设置成为了守护线程,因此当最后由于等待wait只剩下t2线程时,其仍会停止,即只剩下守护线程时,其将停止,无论处于什么状态。
join方法
public final void join() throws InterruptedException :等待该线程终止,**抛出**InterruptException-如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态被清除。
(注:会抛出异常的时候,要么在所在函数的声明位置加上throws Exception,要么将其放入try{}catch{}块中)
class DemoTest implements Runnable{ public void run(){ for (int x=0;x<50;x++){ System.out.println(Thread.currentThread().getName()+"......"+x); } }}public class JoinDemo { public static void main(String[] args) throws Exception{ DemoTest d = new DemoTest(); Thread t1 = new Thread(d); Thread t2 = new Thread(d); t1.start(); //临时加入一个线程运算时可以使用join方法 t1.join();//t1线程要申请加入进来运行,主线程等待t1终止之后再执行,即此时主线程处于冻结状态,是可以使用interrupt方法强制恢复回来的 t2.start(); t2.setPriority(Thread.MAX_PRIORITY); //t1.join();//t1线程要申请加入进来运行,主线程等待t1终止之后再执行,注意此时开启的线程是t1与t2,即t1与t2互相争夺执行权,但是主线程仅仅与t1线程相关联,在线程t1执行结束后主线程开始执行 for (int x=0;x<50;x++){ System.out.println(Thread.currentThread().getName()+"......"+x); } }
优先级
优先级越高代表被cpu执行的概率越大(1到10),一般1、5与10的差距是最大的。
因为是静态常量,因此需要加上类名
字段摘要:Thread.MAX_PRIORITY,线程可以具有的最高优先级;Thread.MIN_PRIORITY,线程可以具有的最低优先级;Thread.NORM_PRIORITY,分配给线程的默认优先级,例如:
t2.setPriority(Thread.MAX_PRIORITY);
Thread.yield()方法
yield():暂停当前正在执行的线程对象,并执行其他线程
yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。
因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。例如:
class DemoTest implements Runnable{ public void run(){ for (int x=0;x<50;x++){ System.out.println(Thread.currentThread().getName()+"......"+x); Thread.yield(); } }}
- 多线程学习笔记(七)之wait与sleep的区别、线程停止及守护线程等
- java个人学习笔记20(wait()和sleep()区别+停止线程+interrupt()+join()+setDaemon()+setPriority()+多线程常见写法)
- 32-多线程(wait和sleep的区别)1 2 33-多线程(停止线程方式-定义标记) 35-多线程(守护线程-setDaemon).1 2
- 线程 and 多线程中sleep()、wait()方法等得区别?
- java线程wait与sleep的区别
- 记下线程中sleep()与wait()的区别
- 【线程】java之Thread.sleep(long)与object.wait()/object.wait(long)的区别及相关概念梳理
- sleep与wait 区别 sleep用于线程控制,而wait用于线程间的通信
- java多线程三种方式区别,java多线程,线程同步方式,线程同步加锁的方法,wait与sleep区别
- java线程同步原理及wait,notify的用法及与sleep的区别
- java线程同步原理及wait,notify的用法及与sleep的区别
- java线程同步原理及wait,notify的用法及与sleep的区别
- java线程同步原理及wait,notify的用法及与sleep的区别
- java线程同步原理及wait,notify的用法及与sleep的区别
- java线程同步原理及wait,notify的用法及与sleep的区别
- java线程同步原理及wait,notify的用法及与sleep的区别
- 07_多线程停止与守护线程
- java线程同步原理、wait,notify的用法及与sleep的区别
- LintCode 73 前序遍历和中序遍历树构造二叉树
- 不是我不会演戏
- OpenCV(学习笔记8)-OpenCV模块介绍
- Mongodb重难点解析(一、基本理解与操作)
- 算法导论程序2--归并排序(Python)
- 多线程学习笔记(七)之wait与sleep的区别、线程停止及守护线程等
- 6.搜索
- 受限的用户SHELL环境
- react-native 写一个大的checkbox
- TK1学习笔记三:安装OpenCV
- DB2第一步 — 创建表
- 第二届CCPC女生赛 粗略题解(要做重现的不要看哦)
- 如何在局域网访问Tomcat项目
- Java中String,StringBuilder,StringBuffer的区别