线程相关面试问题

Threads
    线程是指进程中的一个执行流程,一个线程由多个线程组件,即在一个进程中可以执行多个线程。即在一个进程中可以运
行多个线程,当进程内的多个线程同时运行,这种方式称为并发运行。
    不同进程之间不能共享代码和数据空间,而同一进程的不同线程可以共享代码和数据空间。
    进程和线程的主要区别就是:每个进程都需要操作系统为其分配独立的内存地址空间,而同一进程的所有线程在同一块
地址空间中工作,这些线程可以共享同一块内存和系统资源。
 
  java中的线程。
  分为 前台线程 -- 执行线程 
        后台线程-- 守护线程和精灵线程。
  Thread类的 run()方法是专门被自身的线程执行的,主线程不能调用,否则违背了Thread类提供run()方法的初衷。
  
    1 新建状态。(New)
        用new语句创建的线程对象处于新建状态。仅仅在堆区分配了内存;
    2 就绪状态 (Runable)
        当一个线程对象创建后,其他线程调用他的start()方法, 线程进入就绪状态,这个线程位于可运行池中,
            等待获得CPU的使用权。
    3 运行状态(Running)
        这个状态线程占用CPU,执行程序代码,在并发运行环境中,如果,计算机只有一个CPU那么任何时间只有一个线程处
    于这个状态,若有多个CPU,那么同一时刻,可以让几个线程占用不同的CPU使他们都处于运行状态,只有处于就绪状态的
    线程才有机会,转到运行状态。
    4 阻塞状态 (Blocked)
        当线程处于阻塞状态时,java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,才有机会进入运行状态。
        分三种 
        位于对象等待池中的阻塞状态。运行状态执行了某个对象的wait()方法;
        位于对象锁池中的阻塞状态:线程处于运行状态,但同步锁被其他线程占用,java虚拟机就会把这个线程放到这个对
        象的锁池中,
        其他阻塞状态: 当前线程执行了sleep()方法,或者调用其他线程的join()方法,或者发出了I/O请求时,就会进入
        这个状态,当一个线程执行System.in.read()方法时,就会发出一个I/O请求,该线程放弃CpU。
    5,死亡状态(Dead)
        当线程退出run()方法时,就会进入死亡状态。线程正常结束生命状态或是异常结束,都不会对其他线程造成影响。

    6 void sleepingThread.interrupt() 中断某个线程的阻塞状态。
    7 boolean otherThread.isInterrupted() 测试某个线程是否被中断
    8 void join() 挂起当前线程,直至它所调用的线程终止才被运行, 谁调用谁阻塞
    9 wait()  执行该方法的线程执行释放对象的锁。java虚拟机把该线程放到该对象的等待池中,该线程等待其它线程将其唤醒。
        notify() 从对象的等待池中随机选择一个线程,把它转到对象的锁池中,如果对象的等待池中没有任何线程,那么notify()方法
            什么也不做。
        wait() notify() notifyAll(),这三个只能写在同步代码块。
        线程的死锁: A线程在等待B线程持有的锁。而B线程等待A线程持有的锁。
        线程的让步:Thread.yield() 方法,如果此时具有相同优先级的线程处于就绪状态,那么yiled()方法将把当前运行的线程放到
        可运行池中使另一个线程的运行,若没有相同优先级的可运行线程,则yield()什么也不做。
        sleep()和yield()方法都是Thread类的静态方法。都会使当前运行的线程放弃CPU把运行机会让给别的线程。
            sleep()方法不考虑其他线程优先级,
            yield()只会给相同优先级或者更高优先级的线程一个运行机会,
            sleep()方法转到阻塞状态, yield()方法转到就绪状态。
            sleep()方法会抛出InterruptedExcetion,yield()方法不会抛出异常。
            sleep()比yield()方法具有更好的可移植性。
            yield(),方法唯一用途是测试期间认为提高册程序的并发性能,以帮助发现一些隐藏的错误。 所以并不常用。
    10  关于interrupt,isInterrupted,Interrupted三个方法的理解。
         interrupt,和isInterrupted,是Thread类中的非静态方法,可以用线程对象来访问。  t.interrupt() t.isInterrupted()
         Interrupted是Thread类中的静态方法,可以用类名来访问 Thread.interrupted();
         interrupt可以用来中断线程
         interrupted isInterrupted 可以用来判断线程是否被中断过。
         一个线程A是不可能调用线程B的interrupt方法来中断B线程的运行。
         因为线程A调用线程B的interrupt方法的时候,线程A肯定是在使用cup运行这个中断方法的代码,这个线程B肯定
         没有在使用CPU运行代码了(同一时刻只可能有一个线程使用CPU在运行代码),所以就谈不上说线程A调用线程B
         的interrupt方法把正在运行的线程B给中断了。
         一个线程在使用CPU运行时可以自己调用interrupt来中断自己,交出CPU,回到就绪状态。
         那就是每一个线程对象中有一个特殊的标记,那就是可以标记出这个线程有没有被其他线程进行尝试中断过。
         因为线程A中是可以调用线程B的interrupt方法来尝试中断线程B的,虽然这样的中断并不能起真正的中断作用。
         但是可以把线程B对象中的某个标识。从false改为true表示在某个情况下,有其他线程想中断你了。
         那么也就是说。我们可以在线程A中通知线程B,我在某个条件满足的情况下,至少尝试着调用你的interrupt方法
         去中断你了。然后这个时候线程B在运行的时候,过程中就可以通过另外俩个方法 isInterrupted和interrupted
         来知道是否有其他线程在试图中断自己了。然后就是线程B根据这个信息,来决定自己是否要中断自己。或者继续
         运行下去。
         当在线程B执行的代码中调用Thread.interrupted()方法的时候,会显示出是否有其他线程视图中断自己也就是
         线程B,如果显示为true,注意了。这个时候Thread.interrupted()会接着把这个状态信息,从true改为false,
         因为线程B可能被另外多个线程多次中断,这个方法就可以让我们把之前的中断信息给抹去,因为有可能线程B里
         面根本不想理会之前的中断信息。 isInterrupted是非静态方法。可以用对象来调用,它也能返回ture或者false
         来表示线程B,是否有被其他线程尝试中断的情况。但是这里并不会修改这个信息,也就是如果这时候显示为true
         。那么之后也会显示为ture,这一点和静态方法 interrupted不一样的,
         
    最后一个问题:
        为什么,线程在wait或者sleep期间被中断的时候会抛出InterruptedException呢。
        因为处于这些状态的线程是不可能拿到CPU的使用权的。那么意味着即使我调用你的interrupted方法去尝试的通知
        “我试图去中断你了“, 那么你也是不可能拿到CPU的使用权去处理的我的这种中断的通知信息的,所以这时候就会
        抛出异常了,(当然我们也可以利用这个特点来改变一个阻塞状态线程的状态)
 
        
        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值