阿里面試官:你連個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相關技術文章或行業資訊,歡迎大家關注和轉發文章!