Concurrent programming related interview questions

1. The relationship between processes and threads as well as coroutines

  process:

    Simple process to understand is that the program we normally use, such as QQ, browser, network disk and so on. The process has its own separate memory address space,

    We have more than one thread.

  Thread:

    Thread can be understood as a lightweight process, it is the smallest unit of program execution. After a process starts, it will generate a default main thread,

    The main thread can create multiple child threads,

            

 

              

 

 

       

 

 

 

  HS:

      HS, also called micro-threads, shred. Hiap Seng is a thread of execution, but a bit like a multi-threaded execution, high efficiency in the implementation HS

      Simply put Hiap Seng is an upgraded version of processes and threads, processes drink threads are faced with the problem of switching within kernel mode and user mode while

    Spend a lot of time to switch, and the achievements of the Association is the user control over when to switch, no longer need to fall into kernel mode system.

 

  A program has at least one process, a proceeds of at least one thread. Threads can not execute independently, they must exist in accordance with the process.

  HS, application level (rather than the operating system) controls the switch in order to enhance efficiency.


2. The difference between the parallel and concurrent

  Parallel (parallel):

        Refers to at the same time, a number of instructions executed simultaneously on multiple processors. So in terms of the microscopic or macroscopic point of view

        Both are performed together.

        

  summary:

    When the system has more than one CPU, then it is possible to operate the thread non-concurrent. When a CPU executes a thread, another

     The CPU can execute another thread, two threads and do not seize the CPU resources, may be performed simultaneously, we call such a manner parallel (Parallel).

 

 

 


  Concurrency (concurrency):

        At the same time, only refers to the execution of an instruction, but instruction is executed multiple threads fast rotation, making

        Has the effect of simultaneous execution of multiple threads at the macro, micro, but not executed simultaneously, just

        Time is divided into several segments, a plurality of processes performed rapidly alternating

            

  summary:

    When there are multiple threads in operation, if the system is only one CPU, then it simply can not be true at the same time more than one thread,

    It can only CPU time is divided into several periods, then the period of time allocated to each thread of execution, in a time period

    Threaded code is running, other threads in a suspended state. In this way we call concurrent (Concurrent).

  
In 3.Java way multithreaded implementations of Java multi-threaded implementation, there are four: the Thread class inheritance, implement Runnable, implement Callable interface to create Thread by thread FutureTask wrapper
  

  Use ExecutorService, Callable, Future have realized returns the result of multi-threading.

  The first two ways in which the threads are not after the implementation of the return value, the latter two with a return value.


  1, inheritance Thread class to create threads
    on the Thread class is essentially implements an instance of Runnable interface, representing an instance of a thread. The only way to start the thread is () instance method by start Thread class.

    start () method is a native method, it will start a new thread, and executes run () method. This is very simple way to achieve multi-threaded, through their classes directly extend Thread,

    And replication run () method, you can start a new thread and execute the run () method define yourself. E.g:  

public class MyThread extends Thread {  
  public void run() {  
   System.out.println("MyThread.run()");  
  }  
}  
 
MyThread myThread1 = new MyThread();  
MyThread myThread2 = new MyThread();  
myThread1.start();  
myThread2.start(); 

  

  2、实现Runnable接口创建线程
  如果自己的类已经extends另一个类,就无法直接extends Thread,此时,可以实现一个Runnable接口,如下:  

public class MyThread extends OtherClass implements Runnable {  
  public void run() {  
   System.out.println("MyThread.run()");  
  }  
}  

  为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例: 

MyThread myThread = new MyThread();  
Thread thread = new Thread(myThread);  
thread.start();  

  3、实现Callable接口通过FutureTask包装器来创建Thread线程

  Callable接口(也只有一个方法)定义如下:     

public interface Callable<V>   { 
  V call() throws Exception;   } 
public class SomeCallable<V> extends OtherClass implements Callable<V> {

    @Override
    public V call() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

}
Callable<V> oneCallable = new SomeCallable<V>();   
//由Callable<Integer>创建一个FutureTask<Integer>对象:   
FutureTask<V> oneTask = new FutureTask<V>(oneCallable);   
//注释:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。 
  //由FutureTask<Integer>创建一个Thread对象:   
Thread oneThread = new Thread(oneTask);   
oneThread.start();   
//至此,一个线程就创建完成了。

 

4.Callable和Future模式

 https://www.cnblogs.com/szhhhh/p/12553278.html

5.线程池创建的方式(一般不适用Excecutors.nexxxx创建,一般使用ThreadPoolExecutor)

  Java通过Executors(jdk1.5并发包)提供四种线程池,分别为:
  newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。  

public static void main(String[] args) {
        //1.创建可缓存的线程池,可重复利用
        ExecutorService newExecutorService = Executors.newCachedThreadPool();
        //创建了10个线程
        for (int i = 0; i < 10; i++) {
            int temp = i;
            newExecutorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("threadName;"+Thread.currentThread().getName()+",i"+temp);
                }
            });
        }

    }

 


  newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

 public static void main(String[] args) {
        //1.创建可固定长度的线程池
        ExecutorService newExecutorService = Executors.newFixedThreadPool(3);
        //创建了10个线程
        for (int i = 0; i < 10; i++) {
            int temp = i;
            newExecutorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("threadName;"+Thread.currentThread().getName()+",i"+temp);
                }
            });
        }

    }

 


  newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

 public static void main(String[] args) {
        //1.创建可定时线程池
        ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(5);
        for (int i = 0; i < 10; i++) {
            final int temp = i;
            newScheduledThreadPool.schedule(new Runnable() {
                public void run() {
                    System.out.println("i:" + temp);
                }
            }, 3, TimeUnit.SECONDS);
        }

    }

 


  newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

public static void main(String[] args) {
        //1.创建单线程
        ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            newSingleThreadExecutor.execute(new Runnable() {

                @Override
                public void run() {
                    System.out.println("index:" + index);
                    try {
                        Thread.sleep(200);
                    } catch (Exception e) {
                        // TODO: handle exception
                    }
                }
            });
        }
        newSingleThreadExecutor.shutdown();
    }

 


6.Java当中线程状态有哪些

  1. 创建状态:在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。

  2.就绪状态:当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,

    此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

  3.运行状态:线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。

  4.阻塞状态:线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。

  5.死亡状态:如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。

 

 

7.多线程中的常用方法  

  7.1 public void start()  使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

  7.2 public void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。

  7.3. public final void setName(String name) 改变线程名称,使之与参数 name 相同

  7.4 public final void setPriority(int piority) 更改线程的优先级。

  7.5 public final void setDaemon(boolean on) 将该线程标记为守护线程或用户线程。

  7.6 public final void join(long millisec) 等待该线程终止的时间最长为 millis 毫秒。

  7.7 public void interrupt() 中断线程。

  7.8 public final boolean isAlive() 测试线程是否处于活动状态。

  7.9 public static void static yield() 暂停当前正在执行的线程对象,并执行其他线程。

  7.10 public static void sleep(long millisec) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。

  7.11 public static Thread currentThread() 返回对当前正在执行的线程对象的引用。

  

 

 

 


8.线程状态流程图
    
9.volatile关键字有什么用途,和Synchronize有什么区别

  volatile:

    volatile用来修饰变量例如:Thread类里面的表示名字的字符数组其作用是保证数据的可见性和有序性,但它并不能保证数据的原子性

    

 

 

 

    因为volatile不能保证原子性,所以就需要关键字 synchronized

  synchronized:

    它用于修饰代码块和方法,可以弥补volatile关键字的不足,即它能保证对数据操作的原子性,在多个线程对数据进行操作时,保证线程的安全

  小结:    

    1. 修饰对象不同,volatile用于修饰变量,synchronized用与对语句和方法加锁;
    2. 各自作用不同,volatile保证数据的可见性和有序性,但它并不能保证数据的原子性,synchronized可以保证原子性;
    3. volatile不会造成线程堵塞,而synchronized会造成线程堵塞;

  脏读:

    脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,

    另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,

    依据脏数据所做的操作可能是不正确的。

10.指令重排和先行发生原则
  指令重排:

     在计算机执行指令的顺序在经过程序编译器编译之后形成的指令序列,一般而言,这个指令序列是会输出确定的结果;

    以确保每一次的执行都有确定的结果。但是,一般情况下,CPU和编译器为了提升程序执行的效率,会按照一定的规则

    允许进行指令优化,在某些情况下,这种优化会带来一些执行的逻辑问题,主要的原因是代码逻辑之间是存在一定的先后顺序,

    在并发执行情况下,会发生二义性,即按照不同的执行逻辑,会得到不同的结果信息。

  先行发生原则 :

    先行发生是Java内存模型中定义的两项操作之间的偏序关系,如果说操作A先行发生于操作B,

    就是说A产生的影响能被B观察到,“影响”包括修改了内存中的共享变量值、发送了消息、调用了方法等。

    例如:   

// 线程A中执行
i = 1;

// 线程B中执行
j = i;

// 线程C中执行
i = 2;

  如果说线程A是先行发生于线程B的,那么可以确定在线程B执行之后 j=1,因为根据先行发生原则,A操作 i = 1 的结果可以被B观察到,并且线程C还没有执行。


11.并发编程线程安全三要素

  当多个线程要共享一个实例对象的值得时候,那么在考虑安全的多线程并发编程时就要

  保证下面3个要素:     

    原子性(Synchronized, Lock):

      即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。

    有序性(Volatile,Synchronized, Lock)

      即程序执行的顺序按照代码的先后顺序执行。

    可见性(Volatile,Synchronized,Lock):

      指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

      当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取共享变量时,它会去内存中读取新值。



12.进程和线程间调度算法:

  1. 先来先服务(队列)

  2. 最短优先(优先队列)

  3. 高优先权优先调度算

    3.1 优先权调度算法的类型

    3.2 高响应比优先调度算法

  4. 基于时间片的轮转调度算法

    4.1 时间片轮转法

    4.2  多级反馈队列调度算法

  5. 电梯调度算法


13.Java开发中用过哪些锁:

  乐观锁:

      顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间

    别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,在Java中java.util.concurrent.atomic、

    包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换)实现的。

  悲观锁:

      总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,

    这样别人想拿这个数据就会阻塞直到它拿到锁。比如Java里面的同步原语synchronized关键字的实现就是悲观锁。

  

  独享锁:

      是指该锁一次只能被一个线程所持有。

  共享锁:

      是指该锁可被多个线程所持有。

  

  互斥锁:

      在Java中的具体实现就是ReentrantLock。

  读写锁:

      在Java中的具体实现就是ReadWriteLock。

  Reentrant lock:

      Also known as recursive locks, it refers to the same thread acquires the lock of the outer layer method when the lock will automatically get into the inner method.

  

  Fair locks:

      It refers to a plurality of application threads in order to acquire the lock latch.

  Unfair Lock:

      Refers to the order of multiple threads to obtain the lock is not in order to apply the lock, it is possible to apply the thread after thread priority to acquire the lock than prior application. Possible cause priority inversion or hunger.

  Lock segments:

      A lock design is actually not a particular lock, for ConcurrentHashMap, its implementation is complicated to achieve efficient concurrent operation of the lock in the form of segments.

  Spin locks:

      Refers to the attempt to acquire the lock thread does not block immediately, instead of using a circular fashion to try to acquire the lock, this benefit is to reduce the consumption of thread context switching, the drawback is that the cycle will consume CPU. Distributed in:  Distributed Lock:


 
 

      Distributed Lock is common access to shared resources between different systems or distributed control system to achieve lock, if a resource is shared between different systems or different hosts of the same system,

      Often they need to be mutually exclusive to prevent interference with each other to ensure consistency.
 Database:
  row lock:

     Large overhead, locking slow; there will be a deadlock; lock small size, low probability of lock conflicts, high concurrency

  Table lock:

    Overhead small, locked fast; not deadlock; large locking strength, high probability of lock conflicts, the lowest degree of concurrency

  Page locks:

    Cost and locked speed between the table and row locks; there will be a deadlock; locking granularity between table and row locks, concurrency general


14.sync keywords understand
    Synchronized keyword solve multiple threads synchronize access to resources between, synchronized keyword can be guaranteed by its modified method or block of code at any time, only one thread of execution.
  

Guess you like

Origin www.cnblogs.com/szhhhh/p/12592691.html