一、线程中断常用方法
- setName //设置线程名称,使之与参数name相同
- getName //返回该线程的名称
- start //使该线程开始执行;java虚拟机底层调用该线程的start()方法
- run //调用线程对象的run方法
- setPriority //更改线程的优先级
- getPriority //获取线程的优先级
- sleep //在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
- interrupt //中断线程,一般是停止休眠,去执行run方法
1.1 注意事项和细节
- start底层会创建新的线程,调用run,run就是一个简答的方法调用,不会启动新线程。
- 线程的优先级范围为1-10。MAX = 10,NORM = 5,MIN = 1。
- Interrupt 中断线程,但并没有真正的结束线程,一般用于中断正在休眠的线程。(不让它睡了)
1.2 具体使用
下面编写代码来使用一下上述几个方法,我们的子线程类用来吃包子,吃完100个之后休息20秒再吃,当主线程跟子线程say hi 5次时,打断子线程的休眠。让子线程提前开始继续吃包子。
public class ThreadIterrupt {public static void main(String[] args) throws InterruptedException {//测试相关方法T t = new T();t.setName("小华");t.setPriority(Thread.MAX_PRIORITY);t.start();//启动子线程//主线程输出 5个hi,我就中断子线程的休眠for (int i = 0; i < 5; i++) {Thread.sleep(1000);System.out.println("hi " + i);}System.out.println(t.getName() + " 线程的优先级 = "+ t.getPriority());t.interrupt();//中断t线程的休眠,提前开始吃包子}
}class T extends Thread{//自定义的线程类 public void run() {while (true){for (int i = 0; i < 100; i++) {//Thread.currentThread().getName()//获取当前线程的名称System.out.println(Thread.currentThread().getName() + " 吃包子----" + i);}try {System.out.println(Thread.currentThread().getName() + " 休眠中-------");Thread.sleep(1000*20);//休息20秒后再吃} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName() + "被 Interrupt了");}}}
}
二、线程插队常用方法
- yield: 线程的礼让。让出CPU,让其他线程执行,但礼让的时间不确定,所以礼让不一定成功。线程的执行和调用是由操作系统的内核态来决定的,如果操作系统认为目前的执行yield方法的线程完全有能力去同时执行,可能还会执行该线程。
- join: 线程的插队。插队的线程一旦插队成功,则肯定先执行完插入线程所有的任务。假设有两个线程在等待执行,分别为t1和t2。当CPU执行t1时,t1运行t2.join方法,让t2线程的代码先执行,这就是线程的插队。
使用礼让和插队的方式控制两个线程
主线程和子线程都吃20个包子,由于主线程更为照顾子线程,吃第5个包子时,让子线程先吃完20个包子,之后主线程再吃包子。分别使用yield方法和join方法来进行控制,代码如下图所示。
public class ThreadJoin {public static void main(String[] args) throws InterruptedException {T2 t2 = new T2();t2.start();for (int i = 1; i <= 20; i++) {Thread.sleep(1000);System.out.println("主线程吃了" + i + "个包子");if(i == 5){System.out.println("==============主线程让子线程先吃");//t2.join();//相当于让t2插队先执行对应的run方法t2.yield();//礼让,不一定成功System.out.println("子线程吃完了,主线程你可以去吃包子了");}}}
}class T2 extends Thread{//自定义的线程类 public void run() {for (int i = 1; i <= 20; i++) {try {//System.out.println(Thread.currentThread().getName() + " 休眠中-------");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//Thread.currentThread().getName()//获取当前线程的名称System.out.println("子线程 吃包子----" + i);}}
}
三、用户线程和守护线程
- 用户线程:也叫工作线程,当线程的任务执行完或通知方式结束。
- 守护线程(Daemon): 一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束。
我们可以将普通的线程设置为守护线程,守护线程启动时会跟随的主线程的结束而结束,也是一种控制线程的方式。实例代码如下图所示:
public class GuardThread {//Daemon 守护进程public static void main(String[] args) throws InterruptedException {Guard guardThread = new Guard();guardThread.setDaemon(true);guardThread.start();//如果我们希望当主线程结束后,子线程也自动结束//只需将子线程设为守护线程即可//guardThread.setDaemon(true);先设置再启动,否则报错for (int i = 1; i <= 10; i++) {System.out.println("宝强在辛苦的工作...");Thread.sleep(1000);}}
}class Guard extends Thread{ public void run() {for (;;){//无线循环try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("马蓉和宋喆快乐聊天,哈哈哈----");}}
}