《Java多线程编程核心技术》(一)

概要: 学习使用Thread.currentThread() 了解中断线程的方法 了解sleep方法抛出异常

Thread.currentThread()

Thread.currentThread()方法可返回代码正在被哪个线程调用的信息。

public class Counter extends Thread {

	//构造方法在主线程中被执行
    public Counter() {
        print("constructor begin");

        print("Thread.currentThread().getName()------"+Thread.currentThread().getName());//main
        print("this.getName()-----------"+this.getName());//Thread-0

        print("constructor end");
    }

    @Override
    public void run() {
	    //在子线程中被执行
        print("run begin");

        print("Thread.currentThread().getName()--------"+Thread.currentThread().getName());
        print("this.getName()--------"+this.getName());

        print("run end");
    }


    private void print(String msg){
        System.out.println(msg);
    }
}

public class Run {

    public static void main(String[] args){
        Counter counter = new Counter();

        Thread t = new Thread(counter);
        t.setName("new");
        t.start();
    }
}

/** 执行结果如下:
constructor begin
Thread.currentThread().getName()------main
this.getName()-----------Thread-0
constructor end
run begin
Thread.currentThread().getName()--------new
this.getName()--------Thread-0
run end
*/
复制代码

如上,Counter构造方法是在main线程中执行。run()方法是在new线程中执行的。

this.getName()this指代的是Counter实例,Counter继承Thread,在初始化会设置名称为Thread-0

第二个线程t初始化,名称默认为Thread-1,后续重新赋值为new

停止线程

有三种方法可以使终止线程。 1. 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。 2. 使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。 3. 使用interrupt方法中断线程。

interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程 换句话说,调用该方法的线程会被设置一个“中断”状态,用于判断的中断状态的方法如果返回true说明中断状态被设置了。

如何判断线程的状态是不是停止的?Thread.java类里提供了两种方法: 1)this.interrupted(): 测试当前线程是否已经是中断状态,执行后具有将状态标志置为false的功能。如果这个方法被连续调用两次,第二次调用将返回false。 2)this.isInterrupted(): 测试线程Thread对象是否已经是中断状态,但不清除状态标识。

第一种方法,判断当前线程的状态;第二个方法,判断调用者的中断状态。

源码:

public classs Thread {
    public static boolean interrupted() {
	    return currentThread().isInterrupted(true);
    }

    public boolean isInterrupted() {
    	return isInterrupted(false);
    }
    
    /**
     * Tests if some Thread has been interrupted.  The interrupted state
     * is reset or not based on the value of ClearInterrupted that is
     * passed.
     */
    private native boolean isInterrupted(boolean ClearInterrupted);
}
复制代码

从源码中可以看出,最终调用的是isInterrupted(boolean ClearInterrupted)方法,参数ClearInterrupted可以控制中断状态清除。

验证1: 如下代码虽然调用了interrupted()方法,但是从运行结果来看,线程并未停止。


class MyThread extends Thread{
    @Override
    public void run() {
        for(int i =0;i<1000;i++){
            System.out.println("number"+i);
        }
    }
}
public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyThread t = new MyThread();
        t.start();
        //主线程运行10毫秒之后,中断子线程t。但是并没有效果。仅仅是打了一个标记
        Thread.sleep(10);
        t.interrupt();
    }
}
复制代码

验证2: 从运行结果可以看出,t.interrupted()返回的是当前线程的状态,即main线程,main从未调用过interrupt()方法,未被标记过状态,因此返回的结果都是false

t.isInterrupted()返回的是t线程的中断状态。主线程运行10毫秒之后,调用中断方法,此时返回状态为true,表示t.interrupt()方法生效了。

public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyThread t = new MyThread();
        t.start();  
        //主线程运行10毫秒之后,中断子线程t。     
        Thread.sleep(10);
        t.interrupt();
        System.out.println("当前线程0:"+t.interrupted());
        System.out.println("停止线程1:"+t.isInterrupted());
        Thread.sleep(1000);
        System.out.println("当前线程0:"+t.interrupted());
        System.out.println("停止线程1:"+t.isInterrupted());
    }
}

/**
当前线程0:false
停止线程1:true
当前线程0:false
停止线程1:false
*/
复制代码

验证3: 连续两次调用interrupted()方法,第二次调用将返回false

public class Run {
    public static void main(String[] args) throws InterruptedException {
        Thread.currentThread().interrupt();
        System.out.println("停止线程:"+Thread.currentThread().interrupted());
        System.out.println("停止线程:"+Thread.currentThread().interrupted());
    }
}
/**
停止线程:true
停止线程:false
*/
复制代码

应用interrupt()方法和isInterrupted()方法结合使用,来停止线程。

1.使用break停止线程

public class Counter0 extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 100000; i++) {
            if(this.isInterrupted()){
                System.out.println("已经标记了停止状态,我要退出");
                break;
            }
            System.out.println("number"+i);
        }
        System.out.println("退出for循环,后面依然执行");
}
public class Run {

    public static void main(String[] args){
        try {
            Counter0 counter0 = new Counter0();
            counter0.start();
            Thread.sleep(10);
            counter0.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
number776
number777
number778
number779
number780
已经标记了停止状态,我要退出
退出for循环,后面依然执行
*/
复制代码

使用break的方式并未完全退出子线程,for循环之外的代码仍然在执行

改进:

2.使用抛异常的方式,停止线程执行

public class Counter0 extends Thread {
    @Override
    public void run() {
        try{
            for (int i = 0; i < 100000; i++) {
                if(this.isInterrupted()){
                    System.out.println("已经标记了停止状态,我要退出");
                    throw new InterruptedException();
                }
                System.out.println("number"+i);
            }

            System.out.println("退出for循环,后面依然执行");
        }catch (InterruptedException e){
            System.out.println("捕获异常");
        }
    }
}
/**
number983
number984
number985
已经标记了停止状态,我要退出
捕获异常
*/
复制代码

在沉睡中停止线程

public class Thread implements Runnable{
	/**
	 * Causes the currently executing thread to sleep (temporarily cease
	 * execution) for the specified number of milliseconds, subject to
	 * the precision and accuracy of system timers and schedulers. The thread
	 * does not lose ownership of any monitors.
	 *
	 * @param  millis
	 *         the length of time to sleep in milliseconds
	 *
	 * @throws  IllegalArgumentException
	 *          if the value of {@code millis} is negative
	 *
	 * @throws  InterruptedException
	 *          if any thread has interrupted the current thread. The
	 *          <i>interrupted status</i> of the current thread is
	 *          cleared when this exception is thrown.
	 */
	public static native void sleep(long millis) throws InterruptedException;
}
复制代码

InterruptedException当前线程睡眠中,如果有任何线程中断了当前线程,抛出异常。当抛出异常时,当前线程的中断状态被清除,值为false

举个栗子:

public class Counter0 extends Thread {

    @Override
    public void run() {
        super.run();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            System.out.println("状态标记:"+this.isInterrupted());
            e.printStackTrace();
        }
    }
}
public class Run {
    public static void main(String[] args){
        try {
            Counter0 counter0 = new Counter0();
            counter0.start();
            Thread.sleep(10);
            counter0.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
状态标记:false
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.yolo.thread.Counter0.run(Counter0.java:37)
*/
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值