java面试题解析-线程相关

一 Java中线程的实现方式

线程的创建方式一般回答为四种,当然也有说一种,三种,五种的,但是溯其本源是只有一种的,先赘述一下有哪四种,然后解释为什么其实只有一种。

第一种:继承Thread类 重写run方法  启动线程是调用start方法,这样就会创建一个新的线程。并执行线程的任务。如果直接调用run方法,这样会让当前线程执行run方法中的逻辑。

代码如下

 

第二种 实现Runnable接口 重写run方法 

代码如下

 

第三种 当想 获得线程的执行结果时 可以实现Callable 重写call方法,配合FutuureTask 

代码如下:

 第四种 基于线程池 去构建线程 

第五种  有人将 lambda重写run方法时候 称为第五种

  那么追其底层,实际上都是基于 实现Runnable接口实现 我们打开idea 查看Thread类 我们会发现 实现了Runnable接口。

 此方式将futureTask传递到了Thread类中的有参构造当中

 那么查看FutureTask 如下  我们会发现实现了RunnableFuture接口。那么接着查看此接口 

 

我们发现还是继承了Runnab接口。 

 只不过是在其run方法中写了一套逻辑 将返回结果返回

 最后说一下线程池,我们查看ThreadPoolExecutor 中的worker类 (我们每次构建的线程都是worker) 也是实现了Runnable接口 

所以溯其本源只有一种  说几种都是正确的关键看你怎么去陈述

二 java线程中的状态

一.线程的状态

1.1 从操作系统来说 共有五种状态 如图所示:

 1.2 而java为我们准备了 六种状态 我们查看Thread类源码 如下

​​​​​​​

状态如图

 new :此时刚刚把线程的内存地址分配好并没有启动 start方法还未执行,此时cpu无法调度

runnable :java中不区分就绪和运行统称为此状态,调用了start方法,此时cpu可能正在调度线程。也可能没掉度

blocked : 当持有synchronized锁失败的时候没有拿到锁,线程会阻塞,此时为此状态

waiting ;当调用wait,join等方法时,为此状态,需要手动唤醒。

timed_waiting : 当调用sleep等方法时,时间一到会返回大runnbble状态,不需要手动唤醒

 terminated :run方法执行完毕,线程生命周期结束

下面为对应状态的小demo

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(
        );
        System.out.println(thread.getState());
    }

}

此时状态如图 

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(
                () -> {
                    while (true){

                    }
                }
        );
        thread.start();
        Thread.sleep(500);
        System.out.println(thread.getState());
    }

}

此时状态如图 

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        Thread thread = new Thread(
                () -> {
                    synchronized (obj){

                    }
                }
        );
        synchronized (obj){
            thread.start();
            Thread.sleep(500);
            System.out.println(thread.getState());
        }
    }

}

此时状态如图 

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        Thread thread = new Thread(
                () -> {
                    synchronized (obj) {
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
        );
        thread.start();
        Thread.sleep(500);
        System.out.println(thread.getState());
    }

}

此时状态如图

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        Thread thread = new Thread(
                () -> {
                    try {
                        Thread.sleep(1000);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
        );
        thread.start();
        Thread.sleep(500);
        System.out.println(thread.getState());
    }

}

 此时状态如图

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(
                () -> {
                    System.out.println(666);
                }
        );
        thread.start();
        Thread.sleep(100);
        System.out.println(thread.getState());
    }

}

 此时状态如图

到此六种状态测试完毕 

三 java如何停止线程

1.使用stop方法 :会强制让线程结束,由于太过暴力,不推荐使用

2.使用共享变量 :有的线程通过死循环保持一直执行,所以可以使用共享变量破坏死循环,让线程退出死循环,结束run方法。但是成本有些高,也不推荐。

3.使用interupt方式 :此方式类似于共享变量,在线程内有一个中断标记位。默认false 线程休眠时 修改标记位会抛出异常 InterruptedException

四 sleep和wait方法的区别

1.sleep时Thread类中的静态方法,wait是Object类中的方法

2.执行sleep后线程状态为TIMED_ WAITING,自动被唤醒、wait属于WAITING,需要手动唤醒。

3.sleep方法在持有锁时,执行,不会样放锁资源、wait在执行后,会辉放锁资源。

4.sleep可以在持有锁或者不持有锁时,执行。wait方法必须在只有锁时才可以执行

因为在synchronized底层中,对象头中的markword指向 ObjectMonitor,对ObjectMonitior中的属性进行操作(wait方法会将持有锁的线程从owner扔到Waitset集合中,这个操作是在修改QojectMonitor对象,如果没有持有synchronized锁的话,是无法操作ObjectiMlonitor对象的。)

五 并发编程的三大特性 

1.原子性 

2.可见性

3.有序性

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值