源无极

导航

 

一、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,造成污染。

 

 

 

 

posted on 2019-11-09 12:24  源无极  阅读(344)  评论(0)    收藏  举报