文章目錄
- 一.線程
- 1.基本概念
- 2.一個普通的java程式包括哪些線程
- 二,建立線程
- 1.繼承Thread類,重寫run方法
- 2.實作Runnable接口,重寫run方法
- 3.帶有傳回值的多線程實作 --- 實作callable接口
- 4.基于線程池
- 三,線程狀态
- 1.狀态圖
- 2.過程
一.線程
1.基本概念
- 現代作業系統排程的最小單元是線程,也叫輕量級程序
- 一個程序裡可以建立多個線程
- 每一個線程都擁有各自的計數器,堆棧,局部變量表等屬性,并且可以通路共享的記憶體變量
- 處理線上程之間告訴切換,使使用者感覺好像這些線程同時執行
2.一個普通的java程式包括哪些線程
一個java程式不僅僅是main主線程在運作,還有其他多個線程在同時運作,java程式本身就是一個多線程程式
@Slf4j
public class MultiThread {
public static void main(String[] args) {
// 擷取java線程管理MXBean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// 擷取線程和線程的堆棧資訊(不需要擷取線程的Monitors,synchronizers)
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false,false);
// 列印線程資訊
for(ThreadInfo threadInfo:threadInfos){
log.info("threadName:--------->"+threadInfo.getThreadName());
}
}
}
控制台列印結果:
22:41:44.930 [main] INFO com.kevin.demo.base_of_cconcurrency.MultiThread - threadName:--------->Monitor Ctrl-Break
22:41:44.935 [main] INFO com.kevin.demo.base_of_cconcurrency.MultiThread - threadName:--------->Attach Listener
22:41:44.935 [main] INFO com.kevin.demo.base_of_cconcurrency.MultiThread - threadName:--------->Signal Dispatcher
22:41:44.935 [main] INFO com.kevin.demo.base_of_cconcurrency.MultiThread - threadName:--------->Finalizer
22:41:44.935 [main] INFO com.kevin.demo.base_of_cconcurrency.MultiThread - threadName:--------->Reference Handler
22:41:44.935 [main] INFO com.kevin.demo.base_of_cconcurrency.MultiThread - threadName:--------->main
各個基本線程的作用:
- Monitor Ctrl-Break
- Attach Listener : 線程的職責是接收外部jvm指令
- signal dispather : 去進行分發處理發送給JVM各個不同的子產品處理指令
- Finalizer :調用對象該方法的線程
- Reference Handler :清除引用的線程
- main :主線程
二,建立線程
1.繼承Thread類,重寫run方法
線程執行的任務放于run方法中
@Slf4j
public class NewThread1 extends Thread{
@Override
public void run() {
while (true){
log.info("-----> Thread1111111111111111");
}
}
}
啟動線程,通過調用Thread類的start()方法來啟動一個線程。
// 線程建構方式一
NewThread1 newThread1 = new NewThread1();
newThread1.start();
調用run()和調用start()方法有什麼不同?
- 調用start方法是開啟一個新線程放入到等到隊列中,一旦争奪到cpu資源便開始執行
- 調用子線程的run方法實際上并不會開啟一個新的線程,還是在主線程中
2.實作Runnable接口,重寫run方法
@Slf4j
public class NewThread2 implements Runnable{
@Override
public void run() {
while(true){
log.info("---------> newThread222222222222222");
}
}
}
啟動線程,傳入runnable子類對象
// 線程建構方式二
Thread thread = new Thread(new NewThread2());
thread.start();
3.帶有傳回值的多線程實作 — 實作callable接口
傳回值類型就是Callable中的泛型參數類型T
@Slf4j
public class NewThread3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int i = 0;
while(i<10000){
log.info("--------> newThread333333333333");
i++;
}
return i;
}
}
注意,這裡跟前面兩種方式的不同之處在于要借助一個中間類FutureTask
// 線程建構方式三
FutureTask futureTask = new FutureTask(new NewThread3());
Thread thread3 = new Thread(futureTask);
thread3.start();
//擷取傳回值
int i = (int) futureTask.get();
log.info("-------> "+i);
4.基于線程池
使用線程池可以降低資源消耗,提高響應速度和線程的可管理性
之後會另外總結
@Slf4j
public class NewThead4 {
public static void main(String[] args) {
// 建立線程池
ExecutorService executorService = new ThreadPoolExecutor(5, 10, 500,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
//執行任務
while (true) {
executorService.execute(new Runnable() {
@Override
public void run() {
log.info("------------>newThread444444444444444");
}
});
}
}
}
測試結果:
線程之間在互相争奪cpu資源,誰搶到誰執行
三,線程狀态
1.狀态圖
2.過程
- 線程建立
- 調用start()開始進入運作狀态,但是此時并非馬上就運作任務,需要等到系統cpu配置設定到目前線程資源才能執行任務,Thread.yield()方法作用是:暫停目前正在執行的線程對象(及放棄目前擁有的cup資源),并執行其他線程。
- 線程如果執行正常,将直接完成目前周期
- 若線程執行wait(),則進入等待狀态,在這一狀态中,需要依靠其他線程的通知(喚醒)才能傳回運作狀态
- 還有個就是逾時等待狀态,跟等待狀态不同的是,逾時等待狀态經過指定時間就可以自動傳回運作狀态
- 阻塞,當線程遇到同步方法或者同步代碼塊,則進入阻塞狀态