Java面试-关于线程方面的知识迷惑

关于线程开启的迷惑

为了秋招进行Java基础深入补习,看到Thread源码中有一个Run方法,如下:

    @Override
    public void run() {
        if (target != null) {
            target.run();//private Runnable target;
        }
    }

如果跟我一样小白的同学也许会有疑问,咦,怎么最后在线程中还是由传入的Runnable接口多态调用run()方法的呢?这里应该不是很难理解,我们传入了一个Runnable的子类(更多是使用匿名内部类),之后父对象引用子类对象,然后多态调用run方法
带着这个疑问,我做了以下测试:

public class TestJava {

    public static void main(String[] args) {
        //获取主线程中的线程名字
        System.out.println("Thread"+Thread.currentThread().getName());


        new Thread(new Runnable() {
            @Override
            public void run() {
                //获取该方法执行的线程名字
                System.out.println("Thread"+Thread.currentThread().getName());
            }
        }).start();

        new  Runnable(){
            @Override
            public void run() {
                //获取该方法执行的线程名字
                System.out.println("Runnable"+Thread.currentThread().getName());
            }
        }.run();

        //这里根本就不是开启另外一条线程
        MyRunnable mr = new MyRunnable();
        mr.run();
    }

}

class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("MyRunnable"+Thread.currentThread().getName());
    }
}

测试结果:
这里写图片描述

这里可以看出,除了使用new Thread(Runnable).start()中打印出的线程名字不同之外,其他都是在主线程中运行的,所以其他都没有开启子线程,都是在main线程执行的

理解中断

当线程的run方法执行完毕之后,或者在方法中还没有捕获异常的时候,线程将终止.早前Java中提供了stop方法,其他线程可以调用它来终止线程,但这个方法现在早已被弃用了.现在一般使用interrupt方法来请求中断线程

1.当一个线程调用interrupt方法时候,线程的中断标识位将被置位(中断标识位为true),线程会不时地检测这个中断标识位,以判断线程是否需要被中断.
2.要想知道线程是否被置位,可以调用Thread.currentThread().isInterrupted()
3.如果一个线程被阻塞,就无法检测中断状态.如果一个线程处于阻塞状态,线程会在检查中断标识位时发现中断标识位为true,则会在阻塞状态调用处抛出InterruptedException异常,并且在异常抛出前将线程的中断标识位复位,即重新设置为false.
4.需要注意的是被中断的线程不一定会终止,中断线程只会引起线程的注意,被中断的线程可以决定如何响应中断

测试代码:

public class Main {

    public static int count = 0;

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        System.out.println("我还没有被中断" + ++count);
                        //为了让其进行阻塞状态
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        //抛出这异常之前会把Thread.currentThread().isInterrupted()置为false
                        count = 0;
                        System.out.println("被中断了");
                    }
                }

            }
        });


        t1.start();
        try {
            //这里主要让主线程睡眠,为了确保t1保证开启了
            Thread.sleep(1000);//改为5000更好的
            t1.interrupt();
        } catch (InterruptedException e) {
        }


    }
}

结果:
这里写图片描述

可见:中断线程并不是终止线程的意思,要想使用中断线程来终止线程,就要在抛出异常的时候

                    try {
                        ....
                    } catch (InterruptedException e) {
                        //其实这句话就是把中断状态interrupt=true;
                        Thread.currentThread().interrupt();
                        count = 0;
                        System.out.println("被中断了");
                    }

还有两篇很好的文章:
1.Java 多线程同步与死锁 - 百炼成钢 - 博客频道 - CSDN.NET
2.Java多线程系列目录(共43篇) - 如果天空不死 - 博客园

猜你喜欢

转载自blog.csdn.net/simplebam/article/details/74356809