天天看點

java面試筆試題:同步和異步有何異同

如果資料将線上程間共享.例如正在寫的資料以後可能被另一個線程讀到,或者正在讀的資料可能已經被另一個線程寫過了,那麼這些資料就是共享資料,必須進行同步存取.

    當應用程式在對象上調用了一個需要花費很長時間來執行的方法,并且不希望讓程式等待方法的傳回時,就應該使用異步程式設計,在很多情況下采用異步途徑往往更有效率.

    Java同步:

    基本概念:

    每個Object都會有1個鎖.

    同步就是串行使用一些資源.

    (說明:以下有些例子為了突出重點,省略了不必要的代碼.非凡是省掉了一些成員變量,就是需要同步的對象.)

    1. 多線程中對共享、可變的資料進行同步.

    對于函數中的局部變量沒必要進行同步.

    對于不可變資料,也沒必要進行同步.

    多線程中通路共享可變資料才有必要.

    2. 單個線程中可以使用synchronized,而且可以嵌套,但無意義.

    class Test {

    public static void main(String[] args) {

    Test t = new Test();

    synchronized(t) {

    System.out.println("ok!");

    }

    3. 對象執行個體的鎖

    class Test{

    public synchronized void f1(){

    //do something here

    public void f2(){

    synchronized(this){

    上面的f1()和f2()效果一緻, synchronized取得的鎖都是Test某個實列(this)的鎖.

    比如: Test t = new Test();

    線程A調用t.f2()時, 線程B無法進入t.f1(),直到t.f2()結束.

    作用: 多線程中通路Test的同一個執行個體的同步方法時會進行同步.

    4. class的鎖

    final static Object o= new Object();

    public static synchronized void f1(){

    public static void f2(){

    synchronized(Test.class){

    public static void f3(){

    try {

    synchronized (Class.forName("Test")) {

    catch (ClassNotFoundException ex) {

    public static void g(){

    synchronized(o){

    上面f1(),f2(),f3(),g()效果一緻

    f1(),f2(),f3()中synchronized取得的鎖都是Test.class的鎖.

    g()是自己産生一個對象o,利用o的鎖做同步

    作用: 多線程中通路此類或此類任一個執行個體的同步方法時都會同步. singleton模式lazily initializing屬于此類.

    5. static method

    private static int v = 0;

    public static void f1(){

    //do something, 但函數中沒用用到v

    public synchronized static void f2(){

    //do something, 函數中對v進行了讀/寫.

    多線程中使用Test的某個實列時,

    (1) f1()是線程安全的,不需要同步

    (2) f2()這個靜态方法中使用了函數外靜态變量,是以需要同步.

     Java異步:

    一.    它要能适應不同類型的請求:

    本節用 makeString來說明要求有傳回值的請求.用displayString來說明不需要傳回值的請求.

    二.    要能同時并發處理多個請求,并能按一定機制排程:

    本節将用一個隊列來存放請求,是以隻能按FIFO機制排程,你可以改用LinkedList,就可以簡單實作一個優先級(優先級高的addFirst,低的addLast).

    三.    有能力将調用的邊界從線程擴充到機器間(RMI)

    四.    分離過度耦合,如分離調用句柄(取貨憑證)和真實資料的實作.分離調用和執行的過程,可以盡快地将調傳回.

    現在看具體的實作:

    public interface Axman {

    Result resultTest(int count,char c);

    void noResultTest(String str);

    這個接口有兩個方法要實作,就是有傳回值的調用resultTest和不需要傳回值的調用

    noResultTest, 我們把這個接口用一個代理類來實作,目的是将方法調用轉化為對象,這樣就可以将多個請求(多個方法調)放到一個容器中緩存起來,然後統一處理,因為 Java不支援方法指針,是以把方法調用轉換為對象,然後在這個對象上統一執行它們的方法,不僅可以做到異步處理,而且可以将代表方法調用的請求對象序列化後通過網絡傳遞到另一個機器上執行(RMI).這也是Java回調機制最有力的實作.

    一個簡單的例子.

    如果 1: 做A

    如果 2: 做B

    如果 3: 做C

    如果有1000個情況,你不至于用1000個case吧?以後再增加呢?

    是以如果C/C++程式員,會這樣實作: (c和c++定義結構不同)

    type define struct MyStruct{

    int mark;

    (*fn) ();

    } MyList;

    然後你可以聲明這個結構資料:

    {1,A,

    2,B

    3,C

    做一個循環:

    for(i=0;i<length;i++) {

    if(資料組[i].mark == 傳入的值) (資料組[i].*fn)();

    簡單說c/c++中将要被調用的涵數可以被儲存起來,然後去通路,調用,而Java中,我們無法将一個方法儲存,除了直接調用,是以将要調用的方法用子類來實作,然後把這些子類執行個體儲存起來,然後在這些子類的實作上調用方法:

    interface My{

    void test();

登入

後,您就出現在這裡。

http://writeblog.csdn.net/linghu_java http://writeblog.csdn.net/sony2324 http://writeblog.csdn.net/%B1%BB%C6%C1%B1%CE http://writeblog.csdn.net/xuqingandliyan http://writeblog.csdn.net/lifengsen123 http://writeblog.csdn.net/ade8023 http://writeblog.csdn.net/qq825129090 http://writeblog.csdn.net/chxx55757 linghu_java