1 線程概述
- 線程的核心問題是線程提供了并行解決方案
2 線程的相關(guān)概念
2.1 進(jìn)程
進(jìn)程(Process)是計(jì)算機(jī)中的程序關(guān)于某數(shù)據(jù)集合上的一次運(yùn)動(dòng)活動(dòng),是操作系統(tǒng)進(jìn)行資源分配與調(diào)度的基本單位??梢园堰M(jìn)程簡(jiǎn)單的理解為正在操作系統(tǒng)中運(yùn)行的一個(gè)程序
2.2 線程
1 線程(Thread)是進(jìn)程的一個(gè)執(zhí)行單元。一個(gè)線程就是進(jìn)程中一個(gè)單一順序的控制流,是進(jìn)程的一個(gè)執(zhí)行分支。
2 進(jìn)程是線程的容器,一個(gè)進(jìn)程至少有一個(gè)線程,當(dāng)一個(gè)進(jìn)程中沒有線程時(shí),這個(gè)進(jìn)程就結(jié)束了。
3 在操作系統(tǒng)中是以進(jìn)程為單位分配資源。每個(gè)線程都有各自的線程棧,自己的寄存器環(huán)境,自己的線程本地存儲(chǔ)。
4 主線程與子線程:JVM啟動(dòng)時(shí)會(huì)創(chuàng)建一個(gè)主線程,該主線程負(fù)責(zé)執(zhí)行main方法。主線程就是運(yùn)行main方法的線程。Java中的線程是不孤立的,線程之間存在一些聯(lián)系。如果A線程中創(chuàng)建了B線程,稱B線程為A線程的子線程,相應(yīng)的A線程是B線程的父線程。
2.3 串行、并發(fā)、并行
2.3.1串行(Sequential)
一個(gè)挨著一個(gè)順序執(zhí)行,前面的執(zhí)行完畢后,再執(zhí)行后面的。效率低。
2.3.2 并發(fā)(Concurrent)
一段時(shí)間內(nèi)多個(gè)任務(wù)都在運(yùn)行。效率高。
2.3.3 并行(Parallel)
多個(gè)任務(wù)同時(shí)開始,是并發(fā)的特殊情況。效率高。
如下圖:

3 創(chuàng)建線程的方法
- 方法1:繼承Thread類
- 方法2:實(shí)現(xiàn)Runnable接口
- 方法3:實(shí)現(xiàn)Callable接口
- 方法4:使用線程池創(chuàng)建線程
3.1 繼承Thread類創(chuàng)建線程
//1:定義類繼承 Thread
public class Thread01 extends Thread{
//2:重寫 Thread 父類中的 run()
@Override
public void run() {
System.out.println("子線程");
}
public static void main(String[] args) {
//3)創(chuàng)建子線程對(duì)象
Thread01 t=new Thread01();
//4)啟動(dòng)線程
t.start();
System.out.println("主線程");
}
}
運(yùn)行結(jié)果:
主線程
子線程
代碼分析:
- 調(diào)用線程的start()方法來啟動(dòng)線程。啟動(dòng)線程的實(shí)質(zhì)就是請(qǐng)求JVM運(yùn)行相應(yīng)的線程,這個(gè)線程具體什么時(shí)候運(yùn)行由線程調(diào)度器(Scheduler)決定。
- start()方法的作用:?jiǎn)?dòng)子線程,啟動(dòng)成功的線程會(huì)自動(dòng)調(diào)用run()方法。
- 如果開啟了多個(gè)線程,start()調(diào)用的順序并不一定就是線程啟動(dòng)的順序,多線程運(yùn)行結(jié)果與代碼執(zhí)行順序或調(diào)用順序無關(guān)。線程調(diào)用具有隨機(jī)性
3.2 實(shí)現(xiàn)Runnable接口創(chuàng)建線程
如果線程類已經(jīng)有父類,就不能使用繼承Thread類來實(shí)現(xiàn)線程,此時(shí)可以實(shí)現(xiàn)Runnable接口來創(chuàng)建線程。
public class Thread03_1 implements Runnable{
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println("sub "+i);
}
}
public static void main(String[] args) {
Thread03_1 thread03_1 = new Thread03_1();
Thread thread = new Thread(thread03_1);
thread.start();
for (int i = 0; i <100 ; i++) {
System.out.println("main "+i);
}
}
}
3.3 實(shí)現(xiàn)Callable接口創(chuàng)建線程
Callable接口內(nèi)只有一個(gè)call方法,所以是函數(shù)式接口,能返回線程執(zhí)行結(jié)果,要拋異常,結(jié)合FutureTask類獲取線程的返回值
class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
for (int i = 0; i <5 ; i++) {
System.out.println("call i="+i);
}
return "callable";
}
}
public class CallableDemo {
public static void main(String[] args) {
//創(chuàng)建線程對(duì)象
MyThread myThread=new MyThread();
//將線程對(duì)象包裝到futureTask中,線程返回Stirng類型的值
FutureTask<String> futureTask=new FutureTask<>(myThread);
Thread thread=new Thread(futureTask);
//啟動(dòng)線程
thread.start();
String result= null;
try {
//獲取線程返回結(jié)果
result = (String) futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//輸出返回結(jié)果
System.out.println(result);
}
}
運(yùn)行結(jié)果:
call i=0
call i=1
call i=2
call i=3
call i=4
callable