面試題記錄

1.如何控制線程執行的順序

方案1:前端

經過join方法保證多線程的順序性的特性java

join:讓主線程等待子線程執行完成後,主線程才執行。這裏join是調用的Object的wait方法node

package com.lzy;

public class Main {

    static Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("thread1");
        }
    });
    static Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("thread2");
        }
    });
    static Thread thread3 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("thread3");
        }
    });
    static Thread thread4 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("thread4");
        }
    });


    public static void main(String[] args) throws InterruptedException {

        thread1.start();
        thread1.join();// 這裏的thread1.join是讓主線程wait
        thread2.start();
        thread2.join();
        thread3.start();
        thread3.join();
        thread4.start();
    }
}

方案2:mysql

static ExecutorService executorService = Executors.newSingleThreadExecutor();// FIFO
executorService.submit(thread1);
executorService.submit(thread2);
executorService.submit(thread3);
executorService.submit(thread4);

這種方式是使用了單線程配合隊列(LinkedBlockingQueue)完成的。nginx

代碼git

方案3:web

經過共享對象鎖加上可見變量來實現ajax

public class MyService {  
  
    private volatile int orderNum = 1;  //  共享變量
  
    public synchronized void methodA() {  
        try {  
            while (orderNum != 1) {  
                wait();  // 當前線程讓出CPU
            }  
            for (int i = 0; i < 2; i++) {  
                System.out.println("AAAAA");  
            }  
            orderNum = 2;  
            notifyAll();  // 通知其餘線程啓動
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
  
    public synchronized void methodB() {  
        try {  
            while (orderNum != 2) {  
                wait();  
            }  
            for (int i = 0; i < 2; i++) {  
                System.out.println("BBBBB");  
            }  
            orderNum = 3;  
            notifyAll();  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
  
    public synchronized void methodC() {  
        try {  
            while (orderNum != 3) {  
                wait();  
            }  
            for (int i = 0; i < 2; i++) {  
                System.out.println("CCCCC");  
            }  
            orderNum = 1;  
            notifyAll();  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
}
import service.MyService;  
public class ThreadAA extends Thread {  
  
    private MyService dbtools;  
  
    public ThreadAA(MyService dbtools) {  
        super();  
        this.dbtools = dbtools;  
    }  
  
    @Override  
    public void run() {  
        dbtools.methodA();  
    }  
  
}
import service.MyService;  
public class ThreadBB extends Thread {  
  
    private MyService dbtools;  
  
    public ThreadBB(MyService dbtools) {  
        super();  
        this.dbtools = dbtools;  
    }  
  
    @Override  
    public void run() {  
        dbtools.methodB();  
    }  
  
}
import service.MyService;  
public class ThreadCC extends Thread {  
  
    private MyService dbtools;  
  
    public ThreadCC(MyService dbtools) {  
        this.dbtools = dbtools;  
    }  
  
    @Override  
    public void run() {  
        dbtools.methodC();  
    }  
  
}
import extthread.ThreadCC;  
import service.MyService;  
import extthread.ThreadAA;  
import extthread.ThreadBB;  
  
public class Run {  
  
    public static void main(String[] args) {  
        MyService myService = new MyService();  
        for (int i = 0; i < 2; i++) {  
            ThreadBB output = new ThreadBB(myService);  
            output.start();  
            ThreadAA input = new ThreadAA(myService);  
            input.start();  
            ThreadCC threadCC = new ThreadCC(myService);  
            threadCC.start();  
        }  
    }  
  
}

共享對象鎖,能夠保證每一個方法只能同時有一個線程進入,配合wait和notifyall方法,能夠啓動或者喚醒線程。redis

2.Java中Volatile和Synchronized的區別

1.什麼是JMM算法

JAVA Memory Model

併發過程當中如何處理可見性、原子性、有序性的問題。

併發編程中的兩個關鍵問題

a.線程之間如何通訊;wait()、notify()、notifyall()

    a)共享內存 - 隱式通訊

    b)消息傳遞 - 顯式通訊

b.線程之間如何同步

    在共享內存的併發模型中,同步是顯式作的;synchronized

    在消息傳遞的併發模型中,因爲消息的併發必須在消息接受以前,全部同步是隱式

2.定位內存可見性問題

    什麼對象是內存共享的,什麼不是(見 圖1-1)

    Volatile、synchronized

3.

    a.對於聲明瞭Volatile的變量進行寫操做的時候,JVM會向處理器發送一條Lock前綴指令。會把這個變量所在的緩存行的數據寫回到系統主內存中。

    b.在多個處理器的狀況下,保證各個處理器緩存一致性的特色,就會實現緩存一致性協議

synchronized:可重入鎖、互斥性、可見性。

Volatile 能夠作到原子性、可見性;不能作到複合操做的原子性。

 

Volatile Synchronized
  執行控制
內存可見 內存可見
線程不安全 線程安全
從主存中取數據 鎖加
使用在變量級別 變量、方法 、類
不會線程阻塞 會線程阻塞
不能夠被編譯器優化 能夠被編譯器優化

                                        圖1-1

                          

3.lock接口和synchronized的對比

Lock和synchronized的區別

Java5之後出現的:juc(java.util.concurrent.locks)包

1)Lock是一個接口,而synchronized是Java中的關鍵字,synchronized是內置的語言實現;

2)synchronized在發生異常時,會自動釋放線程佔有的鎖,所以不會致使死鎖現象發生;而Lock在發生異常時,若是沒有主動經過unLock()去釋放鎖,則極可能形成死鎖現象,所以使用Lock時須要在finally塊中釋放鎖;

3)Lock可讓等待鎖的線程響應中斷,而synchronized卻不行,使用synchronized時,等待的線程會一直等待下去,不可以響應中斷;

4)經過Lock能夠知道有沒有成功獲取鎖,而synchronized卻沒法辦到。

5)Lock能夠提升多個線程進行讀操做的效率。

  在性能上來講,若是競爭資源不激烈,二者的性能是差很少的,而當競爭資源很是激烈時(即有大量線程同時競爭),此時Lock的性能要遠遠優於synchronized。因此說,在具體使用時要根據適當狀況選擇。

 

4.多線程基礎知識

線程和進程的概念

一個進程中包含不少線程。

實現多線程的方式

1.繼承Thread類,

2.實現Runnable接口,

3.使用ExecutorService(java5),

4.Callable Future帶返回值的多線程操做

多線程的生命週期

建立、就緒、運行、阻塞、終止

 

分佈式鎖

分佈式鎖是針對多進程同步。

解決方式:

1.經過數據庫的方式解決

create table (

id,

method_name(惟一約束)

……

)

多個進程向數據庫插入數據,返回結果大於1的獲取鎖,那麼就能夠去操做共享資源,釋放鎖是經過刪除數據庫中的這條記錄。這種方式是利用了數據庫設置的惟一約束性。

問題:刪除失敗怎麼辦;insert模式不是重入鎖。

2.zookeeper方式

zookeeper節點特色:持久、持久有序、臨時、臨時有序。而且是樹形、相似文件存儲結構

咱們能夠建立一個鎖節點,而後每一個進程都向這個鎖節點下建立一個臨時有序節點,咱們把建立序號最小的節點做爲得到鎖的進程,帶進程操做完了後,刪除該進程建立的節點,此時剩下的節點中的最小節點就是獲的鎖的進程,可是該進程怎麼知道本身獲取到鎖了呢?其實zookeeper還提供了watch機制,該機制是建立節點時綁定watch,即序號大的watch比他小的相鄰的節點,以此類推,當小節點被刪除後就會通知相鄰大節點。

3.基於redis

setnx命令是隻有當key不存在時才爲key設置值,並返回0和1,能夠根據返回值去判斷誰得到了鎖。

java基礎

1. 集合框架中有哪些是安全的?

線程安全的有Hashtable、Vector、properties

2. 設計模式使用過哪些?

使用過模板模式、單例模式、策略模式、代理模式。

模板模式是使用在命令下發時,使用抽象類實現公共的步驟,主要是數據準備,各自的實現類去完成符合不一樣設備的命令格式的數據,

策略模式是使用在數據解析上,咱們的項目會接受多個平臺的數據,數據同樣可是格式不同,這時就使用了策略模式去解析不一樣格式的數據,返回同一格式的數據。

代理模式主要是使用在短信平臺接入上,項目要求能夠接入多個短信平臺,這時就使用動態代理加載不一樣的實現類。

單例模式主要是用在封裝單線程處理隊列任務的業務場景下,好比把數據放到LinkListBlockQueue中 ,開啓單線程去處理這個隊列。

3. 怎樣實現多線程返回結果

Callable 配合Future實現待返回值的多線程,經過實現Callable的call方法,將callable傳入到線程的submit方法中,最後經過Future獲取結果

4. java 中的排序算法怎樣實現的?

5. hashmap實現

6. Volatile關鍵字的做用

7. 單例模式中加上volatile關鍵字的做用

8.瞭解jvm嗎

9. 雙親委派模型

10. gc運行過程

11. 線程池能夠設置哪些參數

12. 線程池中怎樣給線程命名

13.看過那些書

《重構改善既有代碼的設計》、《java併發編程實戰》、《Effective java》

14.java中給變量賦值是原子操做嗎

        1)除long和double以外的基本類型的賦值操做
        2)全部引用reference的賦值操做
        3)java.concurrent.Atomic.* 包中全部類的一切操做
        count++不是原子操做,是3個原子操做組合

15.動態代理的實現方式

16. cglib動態代理有哪些缺陷

安全

1. 不使用https怎樣防止盜鏈?或者使用過怎樣的簽名方式

對用戶的token,時間戳,參數等進行md5簽名,服務器端判斷是否被篡改。

2. 加解密:AES?

AES、Base64

3.若是jwt中token被盜竊了,怎樣阻止用戶登陸或者鎖定帳號

高併發

1. 秒殺思路?

前端作頁面靜態化處理,使用ajax作時間同步,開啓秒殺後,啓動時加載商品數量好比20個,使用redis的原子操做incr判斷當前是否超過了20人,前20名的請求進入到隊列,並將這20個用戶的信息存入到redis中,開啓單線程去消費隊列中的數據,操做數據庫時,可使用樂觀鎖對數據枷鎖,只要成功了就更新redis中的用戶信息標記爲秒殺成功,前端查詢秒殺結果是經過ajax異步查詢redis中的信息獲得是否秒殺成功,

SOA

1. zookeeper 怎麼使用?

2. ActiveMQ的做用?

實現系統之間的解耦

提供的消息類型有:TextMessage、MapMessage、ObjectMessage、ByteMessage 、StreamMessage

消息模式

p2p:一對一的,只要發送了,不論消費者在不在線,最終均可以接收到

發佈/訂閱:一對多,Topic模式,只有消費者在線才能夠接受 ,也能夠註冊持久化訂閱

2. spring cloud 有哪些模塊

註冊中心Eureka、Ribbon客戶端負載均衡、Feign實現接口調用、Hystrix實現容錯處理、zuul實現網關或者getWay、config實現配置中心。

3. nginx 負載均衡

     輪訓、權重、ip_Hash

4.  爲何nginx性能這麼高
    得益於它的事件處理機制:
        異步非阻塞事件處理機制:運用了epoll模型,提供了一個隊列,排隊解決

5.spring mvc請求過程

6. springbean的生命週期

9.http 常見狀態碼 40一、403

 

 

3. rmi

java語言提供的遠程方法調用,服務接口集成remote,使用Naming.rebind方法發佈服務,客戶端使用Naming.lookup方法調用該服務


框架

1. spring boot 怎樣注入map屬性?

springboot 的配置文件若是是properties就不能注入,若是是yml的就能夠,使用縮進的格式定義key和value值

2. 在使用框架時,遇到哪些問題?

好比咱們常用配置文,並使用@Value註解將數據注入進去,可是我遇到在Controller中不能註冊,老是說找不到,進過資料查找發現確實不能注入,由於spring 和springmvc有父子容器的概念,既是自容器能訪問父容器內容,父容器不能訪問自容器的內容,我只在父容器中配置了,並無在自容器中配置。

3. spring Bean生命週期

4. dubbo 支持那些協議

dubbo(默認)、hessian、http、redis、webservice、rmi、thrift、memached

5.dubbo支持序列化方式

dubbo 、jdk、fastjson、hessian2(默認)

6.zookeeper的數據結構

樹下結構、znode

7.zookeeper使用的哪一個算法

paxos

8.spring中怎樣加載properties的方式

9.

優化

1. 作過哪些優化

2. sql層面作過哪些優化

3. tomcat 優化

數據庫

1. 分庫分表

2. 使用過mycat嗎?

3. 當多張表聯合查詢時,其中一張表的索引不生效,怎樣找出這個索引

使用explain查詢執行計劃

4. mysql 的整數類型有哪些

5.mysql怎樣枷鎖

              select * from table where ? lock in share mode;

                    select * from table where ? for update;

                    insert into table values (…);

                    update table set ? where ?;

                    delete from table where ?;

6.mysql的事物隔離界別

1.讀未提交,2.不可重複讀,3.可重複讀,4.串行化

事務隔離級別 髒讀 不可重複讀 幻讀
讀未提交(read-uncommitted)
不可重複讀(read-committed)
可重複讀(repeatable-read)
串行化(serializable)

7.教師表和學生表,老師之間有繼承性,查出某個老師下的全部學生,表結構能夠從新設計

teacher表

id                                 老師                                          父親id

1 A老師 0
2 B老師 1
3 C老師 3

 

student表

id 學生 老師外鍵id
1 A學生 1老師
2 B學生 2老師

 

其餘

1. 我們公司和你心目中的公司相比,百分制能打多少分

2.你對我們公司瞭解多少

3.你認爲寫好一個程序最重要的是什麼

4.你最看重一個公司的什麼

5.你對將來有什麼規劃

相關文章
相關標籤/搜索