zoukankan      html  css  js  c++  java
  • 面试相关的技术问题--多线程

    本文中意在整理关于多线程相关的面试问题,借助了网络上部分关于问题的解答过程,此处不做出处标记,仅供记录学习,以备遗忘!!!文中如果有讲述不妥或者错误的地方,希望阅者给我留言。

    1.多线程的实现方式
    Java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。


    2.线程的状态转换


    3.如何停止一个线程

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


    4.什么是线程安全,如何保证线程安全

    线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
    保证线程安全的方法:
    不要跨线程访问共享变量
    使共享变量是final类型的
    将共享变量的操作加上同步


    5. Synchronized如何使用
    1).方法声明时使用

    public synchronized void synMethod() {
    //方法体
    }

    2).对某一代码块使用,synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块.此时,线程获得的是成员锁

    public int synMethod(int a1){
    synchronized(a1) {
    //一次只能有一个线程进入
    }
    }

    3). synchronized后面括号里是一对象,此时,线程获得的是对象锁。

    public class MyThread implements Runnable {
    public static void main(String args[]) {
    MyThread mt = new MyThread();
    Thread t1 = new Thread(mt, "t1");
    Thread t2 = new Thread(mt, "t2");
    Thread t3 = new Thread(mt, "t3");
    Thread t4 = new Thread(mt, "t4");
    Thread t5 = new Thread(mt, "t5");
    Thread t6 = new Thread(mt, "t6");
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    t5.start();
    t6.start();
    }
    public void run() {
    synchronized (this) {
    System.out.println(Thread.currentThread().getName());
    }
    }
    } 

    如果线程进入,则得到当前对象锁,那么别的线程在该类所有对象上的任何操作都不能进行.在对象级使用锁通常是一种比较粗糙的方法。为什么要将整个对象都上锁,而不允许其他线程短暂地使用对象中其他同步方法来访问共享资源?如果一个对象拥有多个资源,就不需要只为了让一个线程使用其中一部分资源,就将所有线程都锁在外面
    4).synchronized后面括号里是类,此时,线程获得的是对象锁.


    6. synchronized和Lock的区别
    主要相同点:Lock能完成synchronized所实现的所有功能
    不同:
    1).ReentrantLock功能性方面更全面,比如时间锁等候,可中断锁等候,锁投票等,因此更有扩展性。在多个条件变量和高度竞争锁的地方,用ReentrantLock更合适,ReentrantLock还提供了Condition,对线程的等待和唤醒等操作更加灵活,一个ReentrantLock可以有多个Condition实例,所以更有扩展性。
    2).ReentrantLock必须在finally中释放锁,否则后果很严重,编码角度来说使用synchronized更加简单,不容易遗漏或者出错。
    3).ReentrantLock 的性能比synchronized会好点。
    4).ReentrantLock提供了可轮询的锁请求,他可以尝试的去取得锁,如果取得成功则继续处理,取得不成功,可以等下次运行的时候处理,所以不容易产生死锁,而synchronized则一旦进入锁请求要么成功,要么一直阻塞,所以更容易产生死锁。


    7. sleep和wait的区别(考察的方向是是否会释放锁)
    对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
    sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
    在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。


    8. 如何才能产生死锁
    产生死锁的必要条件:
    (1) 互斥条件:一个资源每次只能被一个进程使用。
    (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
    (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。


    9. 什么叫守护线程,用什么方法实现守护线程
      public final void setDaemon(boolean on)


    10. volatile关键字
     一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
      1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
      2)禁止进行指令重排序
    volatile关键字保证了操作的可见性,但是volatile不能保证对变量的操作是原子性
    volatile关键字能禁止指令重排序,所以volatile能在一定程度上保证有序性
    借用深入学习JAVA虚拟机中的一段话:
    观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令

  • 相关阅读:
    Android应用性能测试
    Jmeter 中使用非GUI启动进行压力测试
    软件工程结对作业01
    第六周进度条
    求一维数组最大最大子数组和
    第五周进度条
    第四周进度条博客
    软件工程个人作业03
    第四周四则运算3 PSP表格
    poj 2096 概率dp
  • 原文地址:https://www.cnblogs.com/myadmin/p/5817235.html
Copyright © 2011-2022 走看看