1. Thread類中常用的一些方法
- 執行緒休眠方法-static void sleep
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
try {
//秒殺---
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"~~~~~~~~~~~~~~~"+i);
}
}
}
- yield 當前執行緒讓出cpu-參與下次的競爭
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
System.out.println(Thread.currentThread().getName()+"~~~~~~~~~~~~~~~"+i);
Thread.yield();//當前執行緒讓出cpu參與下次的競爭。
System.out.println("~~~~~~~~~~~~~~~~");
}
}
}
- join加入當前執行緒上
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t1=new MyThread();
t1.setName("執行緒A");
MyThread2 t2=new MyThread2();
t2.setName("執行緒B");
t1.start();
t2.start();
t1.join(); //t1加入主執行緒上,主執行緒需要等t1執行完畢後才會執行. 如果主執行緒需要等帶t1和t2執行緒的執行結果 做下一步操作時。
for (int i = 0; i <20 ; i++) {
Thread.sleep(10);
System.out.println("main~~~~~~~~~~~~~~~~~~~~~"+i);
}
}
}
- setDaemon()設定執行緒為守護執行緒
//JDK--預設就有一個守護執行緒.GC垃圾回收。
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread t1=new MyThread();
t1.setName("執行緒A");
t1.setDaemon(true);//設定t1為守護執行緒
t1.start();
for (int i = 0; i <20 ; i++) {
System.out.println("main~~~~~~~~~~~~~~~~~~~~~"+i);
}
}
}
2. 解決執行緒安全問題
什麼情況下會出現執行緒安全問題
當多個執行緒操作同一個資源時,則出現執行緒安全問題。
- java如何解決執行緒安全問題
提供了兩種方式:第一種:使用synchronized自動鎖 第二種: 使用Lock手動鎖。
使用鎖相對於把原來的非同步轉換為同步操作。
- 使用synchronized關鍵字解決
它可以使用在方法上,也可以使用在程式碼塊中。
synchronized(共享鎖物件){
同步程式碼塊。}
public class SellTicket implements Runnable {
private int tick = 100;
private static Object o = new Object();
@Override
public void run() {
while (true) {
synchronized (this) {
if (tick > 0) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
tick--;
System.out.println(Thread.currentThread().getName() + "賣了一張票;剩餘:" + tick + "張");
} else {
break;
}
}
}
}
}
public synchronized void sell(){
if (tick > 0) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
tick--;
System.out.println(Thread.currentThread().getName() + "賣了一張票;剩餘:" + tick + "張");
}
}
- 使用Lock手動
Lock它是一個介面,它的實現類。ReentrantLock
public class SellTicket implements Runnable {
private int tick = 100;
private Lock l = new ReentrantLock();
//synchronized使用在方法那麼它的共享鎖為this
@Override
public void run() {
while (true) {
try {
l.lock();//加鎖
if (tick > 0) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
tick--;
System.out.println(Thread.currentThread().getName() + "賣了一張票;剩餘:" + tick + "張");
} else {
break;
}
} finally {
l.unlock();//解鎖
}
}
}
}
- synchronized和lock區別
synchronized可以使用程式碼塊和方法。自動加鎖和釋放鎖。不會出現死鎖問題。
lock它只能使用在程式碼塊中。需要手動加鎖和釋放鎖。如果不釋放鎖,死鎖問題。靈活。它的釋放鎖必須放在finally.
3. 死鎖
執行緒A擁有鎖資源a,希望獲取鎖資源b,執行緒B擁有鎖資源b,希望獲取鎖資源a。 兩個執行緒互相擁有對方希望獲取的鎖資源。可能會出現程式堵塞。從而造成死鎖。
1. 不要使用鎖巢狀。
2. 設定超時時間。--Lock類中tryLock.
3. 使用安全java.util.concurrent下的類。
4. 執行緒狀態
NEW,====新建狀態。
RUNNABLE,===>就緒狀態和執行狀態
BLOCKED,===>堵塞狀態
WAITING,====>等待狀態
TIMED_WAITING,===>時間等待
TERMINATED;===終止。