1、執行緒的狀態
休眠方法:
public static void sleep(long millis)
放棄方法:放棄對時間片的使用
public static void yield()
優先順序方法、守護執行緒方法:
守護執行緒的作用:
JVM 程式在什麼情況下能夠正常退出?
答:當 JVM 中不存在任何一個正在執行的非守護執行緒時,則 JVM 程式即會退出。
如果 JVM 中沒有一個正在執行的非守護執行緒,這個時候,JVM 會退出。換句話說,守護執行緒擁有自動結束自己生命週期的特性,而非守護執行緒不具備這個特點。
2、多執行緒特點以及建立方式
多執行緒的特點是搶佔式
cpu時間片安排執行緒的訪問時間
建立執行緒的方式
繼承Thread方法重寫run()方法
1.用this.getId()和this.getName()獲取執行緒的id和名稱
2.用Thread.currentThread()獲取當前執行緒 //如果當前執行緒沒有繼承Thread類的時候用
3.修改執行緒名稱:呼叫setName方法;利用構造方法 super(name);
public class ThreadTest extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "執行緒方法被呼叫了");
}
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
threadTest.start();
}
}
第二種建立執行緒的方法:
繼承Runnable介面,重寫run方法//這個類是一個run方法的實現類,在main方法中建立Thread執行緒物件時把該方法類傳入Thread中可以建立子執行緒
可以使用匿名內部類的方法直接進行執行緒建立
public class TestRunnable implements Runnable {
@Override
public void run() {
System.out.println("實現了run方法");
}
}
public static void main(String[] args) {
Thread thread = new Thread(new TestRunnable());
thread.start();
}
實現Callable介面,重寫call方法,
- 可以定義返回值
- 可以丟擲異常
public class TestCallable implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
System.out.println("建立成功");
return true;
}
public static void main(String[] args) {
TestCallable callable = new TestCallable();
//建立執行服務
ExecutorService service = Executors.newFixedThreadPool(1);
//提交執行
Future<Boolean> result = service.submit(callable);
boolean isTrue = result.get();
service.shutdownNow();
}
}
但是,Runnable缺少的一項功能是,當執行緒終止時(即run()完成時),我們無法使執行緒返回結果。為了支援此功能,Java中提供了Callable介面。
為了實現Runnable,需要實現不返回任何內容的run()方法,而對於Callable,需要實現在完成時返回結果的call()方法。請注意,不能使用Callable建立執行緒,只能使用Runnable建立執行緒。
另一個區別是call()方法可以引發異常,而run()則不能。
為實現Callable而必須重寫call方法。
3、如何保證執行緒安全性
1.
同步程式碼塊
synchronized{
}
注意執行緒中的迴圈會一直執行,但是會根據時間片分配的時間一直執行,不會從頭開始迴圈
2.
當使用靜態方法時候鎖是(類.class)也就是當前類的型別,非靜態方法鎖是this
3. 死鎖
4、執行緒的同步非同步
Lock鎖
lock鎖和synchronized對比
Lock是顯示鎖(手動開啟和關閉,別忘記關閉鎖) synchronized是隱式鎖,出了作用域自動釋放
Lock只有程式碼塊鎖,synchronized有程式碼塊鎖和方法鎖
使用lock鎖,JVM將花費較少的時間來排程執行緒,效能更好,並且具有更好的擴充套件性(提供更多的子類)
優先使用順序
Lock > 同步程式碼塊 > 同步方法
public class TestLock {
public static void main(String[] args) {
TestLock2 testLock2 = new TestLock2();
new Thread(testLock2).start();
new Thread(testLock2).start();
new Thread(testLock2).start();
}
}
class TestLock2 implements Runnable {
int ticketNums = 10;
//定義Lock鎖
private ReentrantLock reentrantLock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
reentrantLock.lock(); //加鎖
if(ticketNums > 0 ){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "購買了第" + ticketNums-- + "張票");
} else {
break;
}
} finally {
//解鎖
reentrantLock.unlock();
}
}
}
}
5、讀寫鎖、互斥鎖
讀寫鎖的效率比互斥鎖高很多
讀寫鎖關係:寫和寫、寫和讀互斥、讀和讀不互斥
互斥鎖全部都互斥
3、使用執行緒池
- 背景: 經常建立和銷燬,使用量特別大的資源,比如併發情況下的執行緒,對效能影響很大
- 思路: 提前建立好多個執行緒,放入執行緒池中,使用時直接獲取,使用完畢放回池中,可以避免頻繁的建立銷燬,實現重複利用,類似生活中的工共交通工具
- 好處
- 提高了響應速度(減少了建立新執行緒的時間)
- 降低資源消耗(重複利用執行緒池中執行緒,不需要每次都建立)
- 便於執行緒管理(…)
- corePoolSize: 核心池的大小
- maximumPoolSize: 最大執行緒數
- keepAliveTime: 執行緒沒有任務時最多保持多長時間後會終止
blic class Main {
public static void main(String[] args) {
TV tv = new TV();
new Watcher(tv).start();
new Player(tv).start();
}
}