一、currentThread()
(一)
返回代码段正在被哪个线程调用
package com.it.po.thread02; public class MyThread01 extends Thread { public MyThread01() { System.out.println("构造器方法打印:"+Thread.currentThread().getName()); } @Override public void run() { super.run(); System.out.println("run方法的打印:"+Thread.currentThread().getName()); } }
package com.it.po.thread02; public class Run01 { public static void main(String[] args){ MyThread01 myThread01 = new MyThread01(); myThread01.setName("lanpo"); myThread01.start(); } }
构造器方法打印:main
run方法的打印:lanpo
构造器是被main方法调用的。
(二)复杂情况
package com.it.po.thread02; public class MyThread02 extends Thread { public MyThread02() { System.out.println("构造器方法打印:Thread.currentThread().getName()="+Thread.currentThread().getName()); System.out.println("构造器方法打印:this.getName()="+this.getName()); System.out.println("构造器 "+Thread.currentThread().getName()==this.getName()); } @Override public void run() { super.run(); System.out.println("run方法打印:Thread.currentThread().getName()="+Thread.currentThread().getName()); System.out.println("run方法打印:this.getName()="+this.getName()); System.out.println("run "+Thread.currentThread().getName()==this.getName()); } }
package com.it.po.thread02; public class Run02 { public static void main(String[] args){ MyThread02 myThread02 = new MyThread02(); Thread thread = new Thread(myThread02); thread.setName("lanpo"); thread.start(); } }
构造器方法打印:Thread.currentThread().getName()=main 构造器方法打印:this.getName()=Thread-0 false run方法打印:Thread.currentThread().getName()=lanpo run方法打印:this.getName()=Thread-0 false
分析:this.getName()代表线程MyThread02
构造器方法打印:Thread.currentThread().getName()=main //正在发生的线程
构造器方法打印:this.getName()=Thread-0 //当前实例myThread02是死的线程,默认赋值从0开始
false
分析同上
run方法打印:Thread.currentThread().getName()=lanpo
run方法打印:this.getName()=Thread-0
false
修改一下
package com.it.po.thread02; public class Run02 { public static void main(String[] args){ MyThread02 myThread02 = new MyThread02(); /*Thread thread = new Thread(myThread02); thread.setName("lanpo");*/ myThread02.setName("lanpo"); myThread02.start(); } }
印证了分析
总结:
1.一个进程里main是一开始就活着的,但是,它跟main方法半毛钱关系都没有,仅仅是同名罢了
2.谁调用了start函数,谁才把自己交给线程调度器,谁才是活着的线程,否则,管你继承啥,还是实现啥,都是一个普通的对象
3.实现了Runable接口的对象具有运行线程的资格,但是,只要它不被start,它就是一个普通的对象,
有资格,并不代表它就是线程,线程是活着的东西,对象是死的
4.线程可以级级包裹嵌套,就像上边一样,它运行的是:target的run
5.自己调用run的话,仅仅就是一个函数调用,要让调度器去调用,它才是一个线程
二、isAlive()
(一)
判断当前线程是否处于活动状态。
package com.it.po.thread02; public class MyThread03 extends Thread { @Override public void run() { super.run(); System.out.println("run:isAlive()="+this.isAlive()); } }
package com.it.po.thread02; public class Run03 { public static void main(String[] args){ MyThread03 myThread03 = new MyThread03(); System.out.println("begin= "+myThread03.isAlive()); myThread03.start(); System.out.println("end= "+myThread03.isAlive()); } }
begin= false end= true run:isAlive()=true
isAlive的作用就是测试线程是否处于活动状态,活动状态就是线程处于启动且尚未停止状态。
线程“ 活”:线程正在运行或是开始运行的状态。
注意: System.out.println("end= "+myThread03.isAlive()); 其实此值是不确定的,上面打印true是因为 线程myThread03
还没有执行完,修改如下:
package com.it.po.thread02; public class Run03 { public static void main(String[] args) throws InterruptedException { MyThread03 myThread03 = new MyThread03(); System.out.println("begin= "+myThread03.isAlive()); myThread03.start(); Thread.sleep(100); System.out.println("end= "+myThread03.isAlive()); } }
begin= false run:isAlive()=true end= false
在0.1s内线程myThread03 执行完成。
(二)
package com.it.po.thread02; public class MyThread04 extends Thread { public MyThread04() { System.out.println("构造器方法打印:Thread.currentThread().isAlive()="+Thread.currentThread().isAlive()); System.out.println("构造器方法打印:this.isAlive()="+this.isAlive()); } @Override public void run() { super.run(); System.out.println("run方法打印:Thread.currentThread().isAlive()="+Thread.currentThread().isAlive()); System.out.println("run方法打印:this.isAlive()="+this.isAlive()); } }
package com.it.po.thread02; public class Run04 { public static void main(String[] args){ MyThread04 myThread04 = new MyThread04(); Thread thread = new Thread(myThread04); thread.setName("lanpo"); thread.start(); } }
构造器方法打印:Thread.currentThread().isAlive()=true 构造器方法打印:this.isAlive()=false run方法打印:Thread.currentThread().isAlive()=true run方法打印:this.isAlive()=false
修改成 线程 启动myThread04
package com.it.po.thread02; public class Run04 { public static void main(String[] args){ MyThread04 myThread04 = new MyThread04(); // Thread thread = new Thread(myThread04); myThread04.start(); } }
构造器方法打印:Thread.currentThread().isAlive()=true 构造器方法打印:this.isAlive()=false run方法打印:Thread.currentThread().isAlive()=true run方法打印:this.isAlive()=true
三、sleep()方法
该方法的作用是指定的毫秒内让当前 “正在执行的线程” 休眠(暂停执行)。
package com.it.po.thread02; public class MyThread05 extends Thread { @Override public void run() { super.run(); try { System.out.println("run threadName="+Thread.currentThread().getName() +"begin "+System.currentTimeMillis()); Thread.sleep(2000); System.out.println("run threadName="+Thread.currentThread().getName() +"end "+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.it.po.thread02; public class Run05 { public static void main(String[] args){ MyThread05 myThread05 = new MyThread05(); System.out.println("Run05 begin "+System.currentTimeMillis()); myThread05.run(); System.out.println("Run05 end"+System.currentTimeMillis()); } }
Run05 begin 1573298629084 run threadName= main begin 1573298629084 run threadName=main end 1573298631084 Run05 end1573298631084
修改为myThread05启动线程
package com.it.po.thread02; public class Run05 { public static void main(String[] args){ MyThread05 myThread05 = new MyThread05(); System.out.println("Run05 begin "+System.currentTimeMillis()); // myThread05.run(); myThread05.start(); System.out.println("Run05 end"+System.currentTimeMillis()); } }
启动线程结果
Run05 begin 1573298813205 Run05 end1573298813206 run threadName= Thread-0 begin 1573298813207 run threadName= Thread-0 end 1573298815207
四、getId()
取得线程的唯一标识
package com.it.po.thread02; public class getThreadId { public static void main(String[] args){ Thread thread = Thread.currentThread(); System.out.println(thread.getName()+" "+thread.getId()); } }

五、停止线程
停止线程是在多线程中重要的技术,多线程停止问题处理不好会导致超出预期的行为且难以定位
停止线程虽然可以用Thread.stop()方法,但是stop()是不安全的,该方法已经废弃。
大多数停止线程使用的方法是:Thread.interrupt()的方法,虽然方法名称是停止,中止的意思,
但是这个方法不会终止一个正在运行中的线程,还需要加一个判断才行(后面讲解)
java中有以下3中方法可以终止正在运行的线程
1)使用退出标志,使线程正常退出,也就是执行完run()方法之后线程终止。
2)使用stop()方法强行停止,不推荐,stop()和suspend及resume一样都是作废的方法,使用的话会产生不可预料的结果。
3)使用interrupt()的方法中断线程。
(一)、停止不了的线程
使用interrupt()的效果并不像for+brea语句那样,马上停止,它仅仅是在当前线程中打了一个暂停的标记,并不是真的停止。
package com.it.po.thread02; public class MyThread06 extends Thread { @Override public void run() { super.run(); for(int i=0;i<100000;i++){ System.out.println("i= "+(i+1)); } } }
package com.it.po.thread02; public class Run06 { public static void main(String[] args) { try { MyThread06 myThread06 = new MyThread06(); myThread06.start(); Thread.sleep(2000); myThread06.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } } }

结果并没有使线程停止。
如何解决?
(二)判断线程是否是停止状态
this.interrupt()是测试当前线程是否已经中断
this.isInterrupt()测试线程是否已经停止。


1.)
package com.it.po.thread02; public class Run07 { public static void main(String[] args) { Thread.currentThread().interrupt(); System.out.println("是否已经停止1:"+Thread.interrupted()); System.out.println("是否已经停止2:"+Thread.interrupted()); } }
是否已经停止1:true 是否已经停止2:false
为什么第二次为false?
根据官方文档的解释,
interrupted()第二次调用时,会清除中断状态。也就是连续两次调用该方法,该方法返回的是false
2.)
isInterrupted()第二次调用时,不会清除中断状态。也就是连续两次调用该方法,该方法返回的是一样的
package com.it.po.thread02; public class MyThread07 extends Thread { @Override public void run() { super.run(); for(int i=0;i<500;i++){ System.out.println("i= "+(i+1)); } } }
package com.it.po.thread02; public class Run07 { public static void main(String[] args) { try { MyThread07 myThread = new MyThread07(); myThread.setName("poo"); myThread.start(); Thread.sleep(10);//是让当前main线程休眠,让myThread线程运行。 myThread.interrupt(); System.out.println("是否已经停止1:"+myThread.isInterrupted()); System.out.println("是否已经停止2:"+myThread.isInterrupted()); } catch (Exception e) { e.printStackTrace(); } System.out.println("end..."); } }

(三)能停止的线程,异常法
package com.it.po.thread02; public class MyThread08 extends Thread { @Override public void run() { super.run(); for(int i=0;i<500;i++){ if(this.isInterrupted()){ System.out.println("已经是停止状态,我要退出了。。"); break; } System.out.println("i= "+(i+1)); } } }
package com.it.po.thread02; public class Run08 { public static void main(String[] args) { try { MyThread08 my= new MyThread08(); my.start(); Thread.sleep(10); //注意for循环只有500,此时当前线程main不可休眠太久, //否则main线程还没有执行 my.interrupt()的时候,for循环执行完了,无法演示成功 my.interrupt(); } catch (Exception e) { e.printStackTrace(); } System.out.println("end..."); } }

变式一、Run08修改成如下
package com.it.po.thread02; public class Run08 { public static void main(String[] args) { try { MyThread08 my= new MyThread08(); Thread thread = new Thread(my); thread.start(); Thread.sleep(10); //注意for循环只有500,此时当前线程main不可休眠太久, //否则main线程还没有执行 my.interrupt()的时候,for循环执行完了,无法演示成功 thread.interrupt(); } catch (Exception e) { e.printStackTrace(); } System.out.println("end..."); } }

此时是无法停下来的,因为 this.isInterrupted() 指的就是线程my
MyThread08 必须修改如下
package com.it.po.thread02; public class MyThread08 extends Thread { @Override public void run() { super.run(); for(int i=0;i<500;i++){ if(Thread.currentThread().isInterrupted()){ System.out.println("已经是停止状态,我要退出了。。"); break; } System.out.println("i= "+(i+1)); } } }

(四)异常法存在的问题
package com.it.po.thread02; public class MyThread09 extends Thread { @Override public void run() { super.run(); for(int i=0;i<500;i++){ if(this.isInterrupted()){ System.out.println("已经是停止状态,我要退出了。。"); break; } System.out.println("i= "+(i+1)); } System.out.println("我输出了,如果这里是for循环又会执行,线程其实没有停止。。"); } }
package com.it.po.thread02; public class Run09 { public static void main(String[] args) { try { MyThread09 my= new MyThread09(); my.start(); Thread.sleep(10); my.interrupt(); } catch (Exception e) { e.printStackTrace(); } System.out.println("end..."); } }

这种情况,第一个for循环外还有代码,线程还是会运行怎么解决?
package com.it.po.thread02; public class MyThread10 extends Thread { @Override public void run() { super.run(); try { for(int i=0;i<500;i++){ if(this.isInterrupted()){ System.out.println("已经是停止状态,我要退出了。。"); throw new InterruptedException(); } System.out.println("i= "+(i+1)); } System.out.println("我for循环下面。。"); } catch (InterruptedException e) { System.out.println("进入MyThread10的catch方法了。。。"); e.printStackTrace(); } } }
package com.it.po.thread02; public class Run10 { public static void main(String[] args) { try { MyThread10 my= new MyThread10(); my.start(); Thread.sleep(10); my.interrupt(); } catch (Exception e) { e.printStackTrace(); } System.out.println("end..."); } }

(五)在沉睡中停止
如果线程在sleep()下停止,会怎么样?
package com.it.po.thread02; public class MyThread11 extends Thread { @Override public void run() { super.run(); try { System.out.println("run brgin "); Thread.sleep(200000);//到这里main线程获得CPU执行 my.interrupt();模拟沉睡中停止 System.out.println("run end。。"); } catch (InterruptedException e) { System.out.println("在沉睡中被停止进入run的catch。。。"+this.isInterrupted()); e.printStackTrace(); } } }
package com.it.po.thread02; public class Run11 { public static void main(String[] args) { try { MyThread11 my= new MyThread11(); my.start(); Thread.sleep(100); my.interrupt(); } catch (Exception e) { System.out.println("main catch..."); e.printStackTrace(); } System.out.println("main end..."); } }
在sleep状态下停止线程,会进入catch,且清除停止状态值。使其变成false
(六)、停止遇到sleep
package com.it.po.thread02; public class MyThread12 extends Thread { @Override public void run() { super.run(); try { for(int i=0;i<100000;i++){ System.out.println("i= "+(i+1)); } System.out.println("run brgin "); Thread.sleep(200000); System.out.println("run end。。"); } catch (InterruptedException e) { System.out.println("先停止,在遇到sleep,进入catch。。。"+this.isInterrupted()); e.printStackTrace(); } } }
package com.it.po.thread02; public class Run12 { public static void main(String[] args) { MyThread12 my= new MyThread12(); my.start(); my.interrupt(); System.out.println("main end..."); } }

(七)、暴力停止线程,stop()的使用
package com.it.po.thread02; public class MyThread13 extends Thread { private int i = 0; @Override public void run() { super.run(); try { while (true){ i++; System.out.println("i= "+i); Thread.sleep(2000); } } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.it.po.thread02; public class Run13 { public static void main(String[] args) { try { MyThread13 my = new MyThread13(); my.start(); Thread.sleep(8000); my.stop(); } catch (InterruptedException e) { e.printStackTrace(); } } }

注意:只打印四个值。
(七)、方法stop()和java.lang.ThreadDeath异常
package com.it.po.thread02; public class MyThread14 extends Thread { @Override public void run() { super.run(); try { this.stop(); } catch (ThreadDeath e) { System.out.println("进入catch 的方法。。"); e.printStackTrace(); } } }
package com.it.po.thread02; public class Run014 { public static void main(String[] args){ MyThread14 my = new MyThread14(); my.start(); } }

如果强行使用stop(),可能使一些清理性的工作得不到完成,另一种情况就是对锁定的对象进行了解锁,
导致数据得不到同步的处理,出现数据不一样的情况。
(八)、释放锁的不良后果
package com.it.po.thread02; public class SynchronizedObject { private String username="a"; private String password="aa"; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } synchronized public void printString(String username,String password){ try { this.username=username; Thread.sleep(100000); this.password=password; } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.it.po.thread02; public class MyThread15 extends Thread { private SynchronizedObject object; public MyThread15(SynchronizedObject object) { this.object = object; } @Override public void run() { object.printString("b","bb"); } }
package com.it.po.thread02; public class Run015 { public static void main(String[] args){ try { SynchronizedObject object = new SynchronizedObject(); MyThread15 my = new MyThread15(object); my.start(); Thread.sleep(2000); my.stop();//SynchronizedObject 只是赋值了用户名,调用stop,暴力停止线程 System.out.println("用户名: "+object.getUsername()+" 密码 "+object.getPassword()); } catch (InterruptedException e) { e.printStackTrace(); } } }
用户名: b 密码 aa
(九)、使用return停止线程
方法interrupt()和return一起使用也可以起到停止线程的效果
package com.it.po.thread02; public class MyThread16 extends Thread { @Override public void run() { while (true){ if(this.isInterrupted()){ System.out.println("线程停止了。。"); return; //虽然此处没有调用sleep,但是一旦main线程抢到CPU则会执行my.interrupt() } System.out.println("time= "+System.currentTimeMillis()); } } }
package com.it.po.thread02; public class Run016 { public static void main(String[] args) throws InterruptedException { MyThread16 my = new MyThread16(); my.start(); Thread.sleep(100); my.interrupt(); } }

总结:线程停止建议使用 抛异常的方式,因为在catch里面可以对异常信息进行相关的处理
且使用异常流能更好,更方便的控制程序的运行流程,不至于代码中出现很多个return,造成污染。
浙公网安备 33010602011771号