java 多线程面试题

1,什么是线程

a), 什么是线程?

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。

b),线程和进程有什么区别?

线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同任务,不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间,别把它和栈内存搞混,每个线程都用于单独的栈内存用来存储本地数据。

2,线程的状态

新建状态(New):当线程对象被创建后,即进入新建状态,如 Thread t = new MyThread();

就绪状态(Runnable):当调用线程对象的start()方法 如:t.start(); 线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()方法 此线程会立即执行。

运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态,线程要想进入运行状态执行,首先必须处于就绪状态。

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入就绪状态,才有机会再次被CPU调用以进入到运行状态,根据阻塞产生的原因不同,阻塞又可以分为三种:

1.等待阻塞:运行状态中线程执行wait()方法,使本线程进入到等待阻塞状态;

2.同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程所占用),他会进入同步阻塞状态。

3.其他阻塞:通过调用线程的sleep()或join()或发出了i/o请求时,线程会进入到阻塞状态,当sleep()状态超时,join()等待线程终止或则超时,或者i/o处理完毕时,线程重新转入就绪状态。

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

 

3,如何在java中实现多线程

  1. (java中实现多线程)在语言层面有两种方式。java.lang.Thread 类的实例就是一个线程但是它需要调用java.lang.Runnable接口来执行,由于线程类本省就是调用Runnable接口所有你可以继承java.lang.Thread类或者直接调用Runnable接口类重写run()方法实现线程。

  2. (start方法和run方法的区别)start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法效果不一样,当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

  3. (Runnable和callable方法的区别)Runnable和callable都代表那些要在不同的线程中执行的任务,Runnable从jdk1.0开始就有了,callable是在jdk1.5增加的,他们的主要区别是callable的call()方法可以返回值和抛出异常。而Runnable的run()方法没有这些功能,Callable可以返回装载有计算结果的Future对象。

     

     

     

4,java内存模型

Java内存模型规定和指引Java程序在不同的内存架构、CPU和操作系统间有确定性地行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所做的变动能被其他线程可见提供了保证,他们之间是先行发生关系,这个关系定义了一些规则让程序员在并发编程是思路更加清晰。

·线程内的代码能够按照先后顺序执行,这被称为程序次序规则。

·对于同一个锁,一个解锁操作一定要发生在时间上后发生的另一个锁定操作之前,也叫做管程锁定规则。

·前一个对volatile的写操作在后一个volatile的读操作之前,也叫volatile变量规则。

·一个线程内的任何操作必须在这个线程的start()调用之后,也叫做线程启动规则。

·一个线程的所有操作都会在线程终止之前,线程终止规则。

·一个对象的终结操作必须在这个对象构造完成之后,也叫对象终结规则。

·可传递性。

5,java中的volatile变量是什么 

volatile是一个特殊的修饰符,只有成员变量才能使用它,在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其他线程是透明的,volatile变量可以保证下一个读取操作会在前一个写操作之后发生。

6,什么是线程安全?Vector是一个线程安全类吗?

       如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码,如果没错运行结果和单线程运行的结果是一样的,而且其他变量的值也和预期的是一样的,就是线程安全的。

7,一个线程运行时发生异常会怎么样?

简单来说,如果异常没有被捕获该线程将会停止执行,Thread.UncaughtExceptionHandler是用于处理未捕获异常造成线程突然中断强情况的一个内嵌接口,当一个未捕获异常将造成线程中断的时候JVM会使用Thread.getUncaughtExceptionHandler()来查询线程的UNcaughtExcepitonHandler并将线程和异常作为参数传递给handler的uncaughtException()方法进行处理。

 

 

8,如何在两个线程间共享数据?

     你可以通过共享对象来实现这个目的,或者是使用像阻塞队列这样并发的数据结构。

     1,如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个runnable对象中有那个共享对象,例如,买票系统就可以这么做。

     2,如果每个线程执行代码不同,这时候需要不同的runnable对象,例如,设计4个线程。其中两个线程每次对j增加1,另外两个线程对j每次减1,银行存取款

         有两种方法来解决此类问题:

         将共享数据封装成另外一个对象,然后将这个对象逐一传递给各个Runnable对象,每个线程对共享数据的操作方法也分配到那个对象身上完成,这样容易实现针对数据,进行各个操作的互斥和通信。

         将Runnbale对象作为一个类的内部类,共享数据作为这个类的成员变量,每个线程对共享数据的操作方法也封装在外部类,以便实现对数据的各个操作的同步和互斥,作为内部类的各个Runnable对象调用外部类的这些方法。

       1:  每个线程执行的代码相同,可以使用同一个Runnable对象。

package com.tgb.hjy;
/**
 * 多线程共享数据-卖票系统
 * @author hejingyuan
 *
 */
public class SellTicket {
 
	 /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        Ticket t = new Ticket();  
        new Thread(t).start();  
        new Thread(t).start();  
    }  
}
class Ticket implements Runnable{  
	  
    private int ticket = 10;  
    public void run() {  
        while(ticket>0){  
            synchronized (Ticket.class){
                ticket--;  
                System.out.println("当前票数为:"+ticket);  
            }  
        }
    }  
  
}

   2: 简单的多线程间数据共享,每个线程执行的代码不同,用不同的Runnable对象。

       针对这种情况就是在处理共享数据的时候,对处理共享数据的方法添加同步

       


class MyData {  
    private int j=0;  
    public  synchronized void add(){  
        j++;  
        System.out.println("线程"+Thread.currentThread().getName()+"j为:"+j);  
    }  
    public  synchronized void dec(){  
        j--;  
        System.out.println("线程"+Thread.currentThread().getName()+"j为:"+j);  
    }  
 
} 

 

9,什么是线程池,为什么要使用它?

     创建线程要花费昂贵的时间和资源,如果任务来了才创建线程那么响应时间会变长,而且一个进程会创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来相应处理,他们被称为线程池,里面的线程叫工作线程,从JDK1.5开始,java api提供了Executor框架让你可以创建不同的线程池,比如单线程池,每次处理一个任务,数目固定的线程池或者缓存线程池(一个适合很多生存期短的任务的程序的可扩展线程池)   

10,如何检测一个线程是否拥有锁?

       在java.lang.Thread中有一个方法叫holdsLock(),他会返回true,如果当且仅当当前线程拥有某个具体对象的锁。  

 

 

                   

                  

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值