zoukankan      html  css  js  c++  java
  • 线程、多线程

    线程的生命周期:新建、就绪、运行、阻塞、死亡

    1、实现线程是继承Thread类好,还是实现Runnable接口好?

    由于类不支持多重继承,如果要继承其他类,最好是实现线程用Runnable

    2、Thread类的start()方法和run()方法的区别

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

    3、Java的Runnable和Callable有什么不同

    Callable的call()方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能

    4、Java的volatile变量是什么?

    volatile是一个特殊的修饰符,只有成员变量才能使用它,保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了这个变量的值,这个新值对于其他线程来说,是立即可见的。

    5、Java中notify和notifyAll的区别

    notify()方法不能唤醒某个具体的线程,只有当一个线程是等待的时候,它才能用;

    notifyAll()方法唤醒所有线程并允许他们争夺锁,这样确保了至少有一个线程是能继续运行的;

    5.1、wait()、notify()、notifyAll()方法为什么不在Thread类里面?

    这几个方法是Object类的方法。Java提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得;

    wait()、notify()、notifyAll()都属于锁级别的操作,所以把它们定义在Object中,因为锁属于对象;

    5.2 wait()和notify()方法为什么要在同步块中调用?

    Java API强制要求这样做,否则会抛出IllegalMonitorStateException异常,另一个原因是避免wait和notify之间产生竞态条件

    5.3 为什么应该在循环中检查等待条件?

    处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。

    因此当一个等待线程醒来时,不能认为它原来的等待状态仍然是有效的,在notify()方法调用之后和等待线程醒来之前这段时间,它可能会改变

    6、Java中堆和栈对于线程的作用

    每个线程都有自己的栈内存,用于存储本地变量、方法参数、和栈调用。一个线程中存储的变量对其他线程是不可见的;

    堆是所有线程共享的公共内存区域,对象都在堆里创建,为了提升效率,线程会从堆里弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,此时volatile变量就可以发挥作用,它要求线程从主存中读取变量的值。

    7、FutureTask是什么?

    在Java并发程序中FutureTask表示一个可以取消的异步运算

    它有启动和取消运算查询运算是否完成取回运算结果等方法;

    只有当运算完成的时候结果才能取回,若运算未完成,get方法将会阻塞

    一个FutureTask对象可以对调用了Callable和Runnable的对象进行包装,由于FutureTask也是调用了Runnable接口,所以它可以提交给Executor来执行。

    8、Java中interrupted和isInterrupted方法的区别

    主要区别就是interrupted()方法会将中断状态清除,而isInterrupted()方法不会

    Java多线程的中断机制是用内部标识来实现的,调用Thread.interrupt()方法来提示线程应该中断了,并设置中断标识为true。当中断线程调用静态方法Thread.interrupted()方法来检查中断状态时,发现中断标识为true则抛出InterruptedException异常,并将中断状态清零。而非静态方法isInterrupted()用来查询其他线程的中断状态且不会改变中断状态标识。

    9、如何避免死锁?

    死锁指的是两个或以上进程在执行过程中,因争夺资源而造成的一种相互等待的想象;

    死锁发生的四个必要条件:

    (1)互斥条件:一个资源每次只能呗一个进程使用;

    (2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;

    (3)不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺;

    (4)循环等待条件:若干进程之间形成一种头尾衔接的循环等待资源关系。

    避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序做操作,来避免死锁。

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

    Thread.holdsLock()方法,返回true ,则说明当前线程拥有某个具体对象的锁。

    11、Java中synchronized和ReentrantLock有什么不同?

    synchronized关键字来实现互斥,但是不能扩展锁之外的方法或块边界,尝试获取锁时不能中途取消;

    Java 5提供Lock接口来解决这些问题,ReentrantLock类实现了Lock接口,拥有与synchronized相同的并发性和内存语义,还具有可扩展性。

    12、Java中的ReadWriteLock是什么?

    读写锁是用来提升并发程序性能的锁分离技术。

    ReadWriteLock维护一对关联锁,一个用于只读操作一个用于写。在没有写线程的情况下一个读锁可能会同时被多个读线程持有。写锁是独占的,可使用ReentrantReadWriteLock来实现。

    13、volatile变量和atomic变量的区别?

    volatile变量保证写操作发生在后续的读操作之前,但不能保证原子性

    AtomicInteger类提供的atomic方法可以让这种操作具有原子性,如getAndIncrement()方法会原子性的进行增量操作。

    14、若同步块内的线程抛出异常会发生什么?

    会释放锁。(其实无论同步块是正常还是异常退出,线程都会释放锁,在finally块里实现释放锁)

  • 相关阅读:
    java中变量的内存分配
    类加载器的双亲委派机制
    缓存行对齐
    缓存一致性与MESI协议
    Mysql优化之join优化
    MySQL crc32 & crc64函数 提高字符串查询效率
    线程不安全
    学习爱上 systemd
    Ubuntu如何备份和恢复系统
    redis报错overcommit_memory is set to 0
  • 原文地址:https://www.cnblogs.com/blackdd/p/12505176.html
Copyright © 2011-2022 走看看