並行プログラミング関連のインタビューの質問

1.プロセスおよびスレッドならびにコルーチン関係

  プロセス:

    理解するための簡単なプロセスは、QQ、ブラウザ、ネットワークディスクなどとして、プログラムは、我々が通常使用するということです。プロセスは、独自の独立したメモリアドレス空間を持ち、

    私たちは、複数のスレッドを持っています。

  スレッド:

    スレッドは軽量プロセスとして理解することができ、それは、プログラム実行の最小単位です。プロセスが開始された後、それは、デフォルトのメインスレッドを生成します

    メインスレッドは、複数の子スレッドを作成することができます

            

 

              

 

 

       

 

 

 

  HS:

      また、マイクロスレッドと呼ばれるHSは、シュレッド。HIAPセン実行のスレッドであるが、ビット実装におけるマルチスレッド実行、高効率などHS

      簡単に言えばHIAPセンは、プロセスとスレッドのアップグレード版で飲み物スレッドがカーネルモードとユーザーモード間の内部スイッチングの問題に直面しているプロセス

    スイッチに多くの時間を過ごし、そして協会の成果は、カーネルモードのシステムに分類することはもはや必要性を切り替えないようにするとき以上のユーザーコントロールです。

 

  プログラムは、少なくとも1つのスレッドの進行を少なくとも一の工程を有しています。スレッドは、彼らがプロセスに従って存在している必要があり、独立して実行することはできません。

  HSは、アプリケーションレベル(よりむしろオペレーティングシステム)の効率を向上させるためにスイッチを制御します。


2.平行と同時の差

  パラレル(並列):

        同時に指し、命令の数は、複数のプロセッサ上で同時に実行されます。だから、ビューの微視的または巨視的の観点から

        両方が一緒に実行されます。

        

  要約:

    システムに複数のCPUがある場合、スレッド非並行して動作することが可能です。CPUは、スレッドを実行すると、別の

     CPUは、同時に実行することができる、我々はこのように並列(パラレル)を呼び出し、別のスレッド、二つのスレッドを実行することができるし、CPUリソースをつかむありません。

 

 

 


  並行処理(同時実行):

        同時に、唯一の命令の実行を意味するが、命令は、製造、高速回転する複数のスレッドを実行します

        ただ、マクロ、ミクロの複数のスレッドの同時実行の効果を持っていますが、同時に実行されません

        時間をいくつかのセグメントに分割され、複数の処理を交互迅速に行います

            

  要約:

    複数のスレッドが動作してある場合は、システムが唯一のCPUであれば、それは単により多くのスレッドよりも同時にtrueにすることはできません、

    それは唯一のCPU時間は、いくつかの期間に分割されることができ、その後、時間の期間は、期間中に、実行の各スレッドに割り当てられました

    スレッド・コードは、サスペンド状態では、他のスレッドを実行している。我々は(同時)同時呼び出してこのように。

  
実装マルチスレッド3.JavaのようにJavaが実装をマルチスレッド、4つがあります:Threadクラスの継承は、Runnableをは、スレッドFutureTaskラッパーによってスレッドを作成するために、呼び出し可能インターフェースを実装する実装
  

  使用ExecutorServiceの、呼び出し可能、今後は返しますマルチスレッドの結果を実現しています。

  スレッドは戻り値と戻り値、後者の二つの実装後にされていない最初の二つの方法。


  1、スレッド作成する継承Threadクラス
    Threadクラスには、本質的にスレッドのインスタンスを表す、Runnableインタフェースのインスタンスを実装しています。スレッドを開始する唯一の方法は、開始スレッドクラスによって()インスタンスメソッドです。

    スタートは()メソッドがネイティブメソッドである、それは新しいスレッドを開始し、実行は、()メソッドを実行します。これは、直接スレッドを拡張し、そのクラスを介して、マルチスレッド達成するための非常に単純な方法であります

    そして、複製run()メソッドは、新しいスレッドを開始し、run()メソッドは、自分自身を定義する実行することができます。例えば:  

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。

  リエントラントロック:

      また、再帰的ロックとして知られ、それは同じスレッドロックが自動的に内部メソッドに取得するときに外層方法のロックを取得することをいいます。

  

  フェアロック:

      これは、ロックラッチを取得するために、アプリケーション複数のスレッドを指します。

  アンフェアロック:

      ロックを取得するために複数のスレッドの順序を意味することは、適用前よりもロックを取得するためにスレッドの優先順位の後にスレッドを適用することが可能であり、ロックを適用するためにはありません。考えられる原因優先順位の逆転や飢餓。

  ロックセグメント:

      ロックの設計はConcurrentHashMapのために、その実装は、セグメントの形でロックの効率的な同時動作を実現するために複雑であり、実際には特定のロックではありません。

  スピンロック:

      代わりにロックを取得しようとする循環方式を使用しての、すぐにブロックしないロック・スレッドを取得しようとする試みを指し、この利点は、スレッドコンテキストスイッチの消費量を削減することで、欠点はサイクルがCPUを消費するということです。:に分散 分散ロック:


 
 

      分散リソースが異なるシステムまたは同じシステムの異なるホスト間で共有されている場合、ロックは、ロックを達成するために、異なるシステム又は分散型制御システムとの間の共有リソースへの共通のアクセスであり、

      多くの場合、彼らは一貫性を確保するために互いに干渉を防ぐために、相互に排他的である必要があります。
 データベース:
  行ロック:

     大きなオーバーヘッド、低速ロック、デッドロックが存在することになる。ロック小型、ロック競合の確率が低い、高い並行性

  表ロック:

    デッドロックはない;大ロック強度、ロック競合の可能性が高い、並行性の最も低い程度を迅速ロック、オーバーヘッド小

  ページのロック:

    テーブルと行ロックの間のコストとロック速度、デッドロックが存在するであろう。テーブルと行ロックの間のロック粒度、同時実行一般


14.syncキーワードが理解
    同期は、複数のスレッドを解決するキーワード同期キーワード間のリソースへの同期アクセスは、いつでも修正された方法またはコードのブロックによって実行の唯一のスレッドを保証することができます。
  

おすすめ

転載: www.cnblogs.com/szhhhh/p/12592691.html