80の最新java基礎部分の面接問題(五)


自分で整理した面接問題は、みんなを助けることができることを望んで、もっと多くの資料が必要なのは私を信じて、みんなは一緒に勉強して進歩します!
48、同期と非同期の違いは何ですか.どのような場合にそれぞれ使用しますか.例を挙げて説明する.データがスレッド間で共有される場合.例えば、書き込み中のデータが後で別のスレッドに読み出されたり、読み取り中のデータが別のスレッドに書き込まれたりすると、これらのデータは共有データであり、同期アクセスが必要になります.アプリケーションがオブジェクト上で実行に時間がかかるメソッドを呼び出し、メソッドの戻りをプログラムに待たせたくない場合は、非同期プログラミングを使用する必要があります.多くの場合、非同期パスを使用すると効率的になります.
  • 次の2つの方法は同期しますか?class Test{synchronized static void sayHello 3(){
    }   
    
    synchronized void getX(){}
    }50、マルチスレッドにはいくつかの実装方法がありますか?同期にはいくつかの実現方法がありますか?マルチスレッドには、Threadクラスを継承してRunnableインタフェースを実装する実装の2つの実装方法があり、synchronized、waitとnotify wait():1つのスレッドを待機状態にし、保有するオブジェクトのlockを解放する.sleep():実行中のスレッドをスリープ状態にする静的メソッドで、InterruptedException例外をキャプチャするために呼び出されます.notify():待機中のスレッドを起動します.このメソッドを呼び出すと、待機中のスレッドを正確に起動するのではなく、JVMによって起動するスレッドを決定し、優先度ではありません.Allnotity():すべての待機状態にあるスレッドを起動します.すべての起動スレッドにオブジェクトのロックを与えるのではなく、競合させることに注意してください.

  • 51、スレッドを起動するにはrun()ですか、start()ですか.スレッドを起動するにはstart()メソッドを呼び出し、スレッドを準備状態にし、後で実行状態にスケジューリングすることができます.スレッドには特定の実行コードを関連付けなければなりません.run()メソッドは、スレッドに関連付けられた実行コードです.
    52.1つのスレッドが1つのオブジェクトのsynchronizedメソッドに入った後、他のスレッドはこのオブジェクトの他のメソッドに入ることができますか?いくつかの状況に分けます:1.他のメソッドの前にsynchronizedキーワードが追加されているかどうか、追加されていない場合はできます.2.このメソッドの内部でwaitが呼び出された場合、他のsynchronizedメソッドにアクセスできます.3.他のメソッドにsynchronizedキーワードが追加され、内部でwaitが呼び出されていない場合は、できません.4.他の方法がstaticの場合、その同期ロックは現在のクラスのバイトコードであり、非静的な方法はthisを使用するため、非静的な方法と同期できない.
    53、スレッドの基本概念、スレッドの基本状態及び状態の関係
    1つのプログラムには複数の実行スレッドが同時に実行され、1つのスレッドはプログラムの1つの実行スレッドであり、各スレッドには実行するコードが関連付けられている.すなわち、複数のプログラムコードが同時に実行され、各プログラムには少なくとも1つのスレッド、すなわちmainメソッドが実行するスレッドがある.もしcpuだけであれば、どのようにして複数のプログラムを同時に実行することができますか?これはマクロから見ると、cpuはaの手がかりを実行し、bの手がかりを実行し、切り替え時間が速く、a、bが同時に実行されているような感じがします.例えば、みんなが同じオフィスでインターネットを利用しているように、外部のネットワークにリンクされているのは1本だけです.実は、このネットワークはaのデータを転送し、bのデータを転送します.切り替え時間が短いので、みんなは同時にインターネットを利用しているような気がします.
    ステータス:準備完了、実行、synchronizeブロック、waitとsleepが停止し、終了します.waitはsynchronized内部で呼び出さなければなりません.スレッドのstartメソッドを呼び出すとスレッドは準備完了状態に入り、スレッドスケジューリングシステムは準備完了状態のスレッドを実行状態に移行し、synchronized文に遭遇すると、実行状態からブロックに移行し、synchronizedがロックを取得すると、ブロックから実行に移行し、この場合waitメソッドを呼び出して保留状態に移行することができ、スレッドに関連するコードが実行されると、スレッドが終了状態になります.
    54.synchronizedとjavaを簡単に述べる.util.concurrent.locks.ロックの異同?主な同一点:Lockはsynchronizedが実現したすべての機能の主な相違点を完成することができる:Lockはsynchronizedよりも正確なスレッドの意味とより良い性能を持っている.synchronizedは自動的にロックを解放しますが、ロックはプログラマーに手動で解放し、finallyで文から解放しなければなりません.ロックにはさらに強力な機能があります.例えば、tryロック方法はロックをブロックしないで取ることができます.例を挙げて説明します(次の問題をlockで書き換えました):package com.huawei.interview;
    import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;
    public class ThreadTest {
    /**
     * @param args
     */
    
    private int j;
    private Lock lock = new ReentrantLock();
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ThreadTest tt = new ThreadTest();
        for(int i=0;i<2;i++)
        {
            new Thread(tt.new Adder()).start();
            new Thread(tt.new Subtractor()).start();
        }
    }
    
    private class Subtractor implements Runnable
    {
    
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true)
            {
                /*synchronized (ThreadTest.this) {          
                    System.out.println("j--=" + j--);
                    //      ,     ?
                }*/
                lock.lock();
                try
                {
                    System.out.println("j--=" + j--);
                }finally
                {
                    lock.unlock();
                }
            }
        }
    
    }
    
    private class Adder implements Runnable
    {
    
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while(true)
            {
                /*synchronized (ThreadTest.this) {
                System.out.println("j++=" + j++);   
                }*/
                lock.lock();
                try
                {
                    System.out.println("j++=" + j++);
                }finally
                {
                    lock.unlock();
                }               
            }           
        }
    
    }

    }55は、2つのスレッドがjに対して1ずつ増加し、他の2つのスレッドがjに対して1ずつ減少する4つのスレッドを設計する.プログラムを書き出します.以下のプログラムは内部クラスを用いてスレッドを実現し,jの増減時に順序の問題を考慮していない.public class ThreadTest1 { private int j; public static void main(String args[]){ ThreadTest1 tt=new ThreadTest1(); Inc inc=tt.new Inc(); Dec dec=tt.new Dec(); for(int i=0;i<2;i++){ Thread t=new Thread(inc); t.start(); t=new Thread(dec); t.start(); } } private synchronized void inc(){ j++; System.out.println(Thread.currentThread().getName()+"-inc:"+j); } private synchronized void dec(){ j--; System.out.println(Thread.currentThread().getName()+"-dec:"+j); } class Inc implements Runnable{ public void run(){ for(int i=0;i<100;i++){ inc(); } } } class Dec implements Runnable{ public void run(){ for(int i=0;i<100;i++){ dec(); } } } }
    --------手当たり次第に書き直す----------class A{JManger j=new JManager();main(){new A().call();}
    void call{for(int i=0;i<2;i++){new Thread(new Runnable(){ public void run(){while(true){j.accumulate()}}}).start();new Thread(new Runnable(){ public void run(){while(true){j.sub()}}}).start();}}}
    class JManager{private j = 0;
    public synchronized void subtract()
    {
        j--
    }
    
    public synchronized void accumulate()
    {
        j++;
    }

    }
    56、サブスレッドは10回循環して、それからメインスレッドは100を循環して、それからまたサブスレッドに戻って10回循環して、それからメインスレッドに戻ってまた100を循環して、このように50回循環して、プログラムを書き出してください.
    最終的なプログラムコードは以下の通りである:public class ThreadTest{
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ThreadTest().init();
    
    }
    
    public void init()
    {
        final Business business = new Business();
        new Thread(
                new Runnable()
                {
    
                    public void run() {
                        for(int i=0;i<50;i++)
                        {
                            business.SubThread(i);
                        }                       
                    }
    
                }
    
        ).start();
    
        for(int i=0;i<50;i++)
        {
            business.MainThread(i);
        }       
    }
    
    private class Business
    {
        boolean bShouldSub = true;//                    
        public synchronized void MainThread(int i)
        {
            if(bShouldSub)
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }       
    
            for(int j=0;j<5;j++)
            {
                System.out.println(Thread.currentThread().getName() + ":i=" + i +",j=" + j);
            }
            bShouldSub = true;
            this.notify();
    
        }
    
        public synchronized void SubThread(int i)
        {
            if(!bShouldSub)
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   
    
            for(int j=0;j<10;j++)
            {
                System.out.println(Thread.currentThread().getName() + ":i=" + i +",j=" + j);
            }
            bShouldSub = false;             
            this.notify();          
        }
    }

    }
    備考:すぐに上の完全なコードを書くことはできません.最初に書いたコードは以下の通りです.問題は、2つのスレッドのコードが同じ変数を参照しなければならないことです.つまり、この2つのスレッドのコードはデータを共有しなければならないので、この2つのスレッドの実行コードを同じクラスに移すことです.
    package com.huawei.interview.lym;
    public class ThreadTest {
    private static boolean bShouldMain = false;
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        /*new Thread(){
        public void run()
        {
            for(int i=0;i<50;i++)
            {
                for(int j=0;j<10;j++)
                {
                    System.out.println("i=" + i + ",j=" + j);
                }
            }               
        }
    
    }.start();*/        
    
        //final String str = new String("");
    
        new Thread(
                new Runnable()
                {
                    public void run()
                    {
                        for(int i=0;i<50;i++)
                        {
                            synchronized (ThreadTest.class) {
                                if(bShouldMain)
                                {
                                    try {
                                        ThreadTest.class.wait();} 
                                    catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                                for(int j=0;j<10;j++)
                                {
                                    System.out.println(
                                            Thread.currentThread().getName() + 
                                            "i=" + i + ",j=" + j);
                                }
                                bShouldMain = true;
                                ThreadTest.class.notify();
                            }                           
                        }                       
                    }
                }
        ).start();
    
        for(int i=0;i<50;i++)
        {
            synchronized (ThreadTest.class) {
                if(!bShouldMain)
                {
                    try {
                        ThreadTest.class.wait();} 
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }               
                for(int j=0;j<5;j++)
                {
                    System.out.println(
                            Thread.currentThread().getName() +                      
                            "i=" + i + ",j=" + j);
                }
                bShouldMain = false;
                ThreadTest.class.notify();              
            }           
        }
    }

    }jdk 5のコンカレントライブラリを使用して実装:import java.util.concurrent.Executors;import java.util.concurrent.ExecutorService;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import java.util.concurrent.locks.Condition;
    public class ThreadTest{private static Lock lock = new ReentrantLock();private static Condition subThreadCondition = lock.newCondition();private static boolean bBhouldSubThread = false;public static void main(String [] args){ExecutorService threadPool = Executors.newFixedThreadPool(3);threadPool.execute(new Runnable(){public void run(){for(int i=0;i<50;i++){lock.lock(); try{ if(!bBhouldSubThread)subThreadCondition.await();for(int j=0;j<10;j++){System.out.println(Thread.currentThread().getName() + ",j="+ j);}bBhouldSubThread = false;subThreadCondition.signal();}catch(Exception e){ }finally{lock.unlock();}} }
        });
        threadPool.shutdown();
        for(int i=0;i<50;i++)
        {
                lock.lock();                    
                try
                {   
                    if(bBhouldSubThread)
                            subThreadCondition.await();                             
                    for(int j=0;j<10;j++)
                    {
                        System.out.println(Thread.currentThread().getName() + ",j=" + j);
                    }
                    bBhouldSubThread = true;
                    subThreadCondition.signal();                    
                }catch(Exception e)
                {                       
                }
                finally
                {
                    lock.unlock();
                }                   
        }
    }

    }57、Collectionフレームワークの構造を紹介する答え:勝手に問題を発揮して、天南海北の誰が話して、あなたの知識が広くて、理解が透徹していればいい.
    58、Collectionフレームワークで実現するインタフェースの比較