1. 程式人生 > 實用技巧 >阿里面試官:你連個java多執行緒都說不清楚,我招你進來幹什麼

阿里面試官:你連個java多執行緒都說不清楚,我招你進來幹什麼

建立執行緒的方法

  • 繼承Thread類

  • 繼承Thread類,重寫run方法,通過執行緒類例項.start()方法開啟執行緒。

public class TestThread1 extends Thread{
    @override
    public void run(){
        System.out.println("執行緒run方法!");
    }
    
    public static void main(String){
        new TestThread1().start();
    }
}

  • 實現Runnable介面

  • 實現Runnable介面,重寫run方法,通過new Thread(執行緒類例項).start()開啟執行緒

  • 推薦使用該方式,避免java的單繼承侷限性

public class TestThread2 implements Runnable{
	@Override
	public void run() {
		System.out.println("執行緒run方法!");
	}
	
	public static void main(String[] args) {
		new Thread(new TestThread2()).start();
	}
}


  • 實現Callable介面

  • 實現Callable介面,重寫call方法,call方法有返回值

  • 啟動方式:

*   建立執行服務

*   提交執行

*   獲取結果

*   關閉服務
public class TestThread2 implements Callable{
	@Override
	public Boolean call() {
		System.out.println("執行緒call方法!");
		return true;
	}
	
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		
		TestThread2 t1 = new TestThread2();
		TestThread2 t2 = new TestThread2();
		TestThread2 t3 = new TestThread2();
		//建立執行服務
		ExecutorService ser = Executors.newFixedThreadPool(3);
		//提交執行
		Future<Boolean> r1 = ser.submit(t1);
		Future<Boolean> r2 = ser.submit(t2);
		Future<Boolean> r3 = ser.submit(t3);
		//獲取結果
		boolean rs1 = r1.get();
		boolean rs2 = r2.get();
		boolean rs3 = r3.get();
		//關閉服務
		ser.shutdownNow();
	}

執行緒同步

  • 多個執行緒同時操作同一資源,執行緒不安全,變數值紊亂

  • 加鎖

  • 佇列+鎖(synchronized)

  • synchronized預設鎖this,可以顯示指定鎖的物件來修改

1. synchronized修飾方法,執行緒安全方法

public class TestThreadSafe {

    public static void main(String[] args) {
        BuyTicket bt1 = new BuyTicket();

        Thread thread1 = new Thread(bt1,"張三");
        Thread thread2 = new Thread(bt1,"李四");
        Thread thread3 = new Thread(bt1,"黃牛");

        thread1.start();
        thread2.start();
        thread3.start();
    }

}

class BuyTicket implements Runnable{

    private int ticketNumber = 10;

    private boolean flag = true;

    @Override
    public void run() {
        while(flag) {
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void buy() throws InterruptedException {
        //買票
        if(ticketNumber <= 0){
            System.out.println("票賣完了!");
            flag = false;
            return;
        }
        Thread.sleep(100);
        //Thread.yield();
        System.out.println(Thread.currentThread().getName() + "買到了一張票,還剩下"+(--ticketNumber) + "張票!");
    }
}

2. synchronized修飾程式碼塊,執行緒安全程式碼塊

public class TestThreadSafe {

    public static void main(String[] args) {
        BuyTicket bt1 = new BuyTicket();

        Thread thread1 = new Thread(bt1,"張三");
        Thread thread2 = new Thread(bt1,"李四");
        Thread thread3 = new Thread(bt1,"黃牛");

        thread1.start();
        thread2.start();
        thread3.start();
    }

}

class BuyTicket implements Runnable{

    private int ticketNumber = 10;

    private boolean flag = true;

    @Override
    public void run() {
        while(flag) {
            System.out.println(Thread.currentThread().getName() + "準備買票" + flag);
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void buy() throws InterruptedException {
        synchronized(this){
            //買票
            if(ticketNumber <= 0){
                flag = false;
                System.out.println("票賣完了!");
                return;
            }
            Thread.sleep(100);
            //Thread.yield();
            System.out.println(Thread.currentThread().getName() + "買到了一張票,還剩下"+(--ticketNumber) + "張票!");
        }
    }
}

3. 使用可重複鎖ReentrantLock

import java.util.concurrent.locks.ReentrantLock;

public class TestLock {

    public static void main(String[] args) {
        BuyTicket bt1 = new BuyTicket();

        Thread thread1 = new Thread(bt1,"張三");
        Thread thread2 = new Thread(bt1,"李四");
        Thread thread3 = new Thread(bt1,"黃牛");

        thread1.start();
        thread2.start();
        thread3.start();
    }

}

class BuyTicket implements Runnable{

    private int ticketNumber = 1000;

    private boolean flag = true;

  //定義可重複鎖
    private	final ReentrantLock lock = new ReentrantLock();
    
    @Override
    public void run() {
        while(flag) {
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void buy() throws InterruptedException {
        	lock.lock();
            //買票
            if(ticketNumber <= 0){
                System.out.println("票賣完了!");
                flag = false;
            }else {
            	Thread.sleep(100);
                //Thread.yield();
                System.out.println(Thread.currentThread().getName() + "買到了一張票,還剩下"+(--ticketNumber) + "張票!");
            }
            lock.unlock();
    }
}


  • 死鎖

  • 兩個以上的物件鎖,每個執行緒互相佔有對方需要的資源。形成死鎖。

執行緒狀態

  • 新生狀態(new)
  • 就緒狀態(start)
  • 阻塞狀態(sleep、wait、同步鎖定)
  • 執行狀態
  • 死亡狀態 執行緒物件進入死亡狀態後,將不能再次呼叫start()方法再次啟動

執行緒(Thread類)方法

  • setPriority(int newPriority) 更改執行緒優先順序 newPriority從1到10

  • static void sleep(long millis) 使當前正在執行的執行緒休眠指定毫秒,不會釋放執行緒鎖物件

  • void join() 執行緒合併,等待該執行緒終止

  • static void yield() 暫停當前正在執行的執行緒,執行其它執行緒

  • void interrupt() 中斷執行緒

  • boolean isAlive() 該執行緒是否活躍

守護執行緒

  • setDaemon(true) : 設定為守護執行緒

  • 執行緒分為使用者執行緒和守護執行緒

  • JVM虛擬機器確保使用者執行緒執行完畢

  • JVM虛擬機器不用等待守護執行緒執行完畢

         eg:後臺記錄操作日誌,監控記憶體,垃圾回收等待

最後

感謝你看到這裡,看完有什麼的不懂的可以在評論區問我,覺得文章對你有幫助的話記得給我點個贊,每天都會分享java相關技術文章或行業資訊,歡迎大家關注和轉發文章!