一、進(jìn)程和線程
? ? 1、進(jìn)程:正在運(yùn)行的程序
? ? ? ? 是系統(tǒng)進(jìn)行資源分配和調(diào)用的獨(dú)立單位
? ? ? ? 每一個進(jìn)程都有它自己的內(nèi)存空間和系統(tǒng)資源
? ? 2、線程是進(jìn)程中的單個順序控制流,是一條執(zhí)行路徑
? ? ? ? 單線程 即一個控制流,多線程即多個控制流
二、多線程的實(shí)現(xiàn)
1、繼承Thread實(shí)現(xiàn):
定義一個類繼承Thread類
在類中重寫run()方法
創(chuàng)建類的對象
-
啟動線程
代碼示例
public class ThreadDemo extends Thread{
@Override
public void run() {
for (int i = 1;i < 20;i++){
System.out.println(getName()+":"+i);
}
}
public static void main(String[] args) {
ThreadDemo threadDemo1 = new ThreadDemo();
ThreadDemo threadDemo2 = new ThreadDemo();
threadDemo1.setName("線程1");
threadDemo2.setName("線程2");
System.out.println(threadDemo1.getPriority());
System.out.println(threadDemo2.getPriority());
threadDemo2.setPriority(6);
threadDemo1.start();
threadDemo2.start();
System.out.println(Thread.currentThread().getName());
}
}
注意:
- run方法封裝線程執(zhí)行的代碼,直接調(diào)用,相當(dāng)于普通的方法
- start啟動線程,然后由JVM調(diào)用此線程的run方法
獲取和設(shè)置線程名稱
利用getName()即可獲取到線程的名稱,未繼承Thread的使用Thread.currentThread().getName()獲取線程名稱
.setName("")可設(shè)置線程名稱
線程調(diào)度模型
模型分類
? ? 1、分時調(diào)度 所有線程輪流使用CPU的使用權(quán),平均分配每個線程占用CPU的時間片
? ? 2、搶占調(diào)度 優(yōu)先讓優(yōu)先級高的線程使用CPU,如果線程的優(yōu)先級相同會隨機(jī)選擇一個
Thread()類中獲取和設(shè)置優(yōu)先級的方法
- 獲取優(yōu)先級public final int getPriority()
- 設(shè)置優(yōu)先級public final void setPriority(int newPriority)
- Thread.MIN_PRIORITY 值為1
- Thread.MAX_PRIORITY 值為10
- ThreadDemo.NORM_PRIORITY 值為 5
- 線程優(yōu)先級高僅僅表示獲取CPU時間片的幾率高,并不是每次都會優(yōu)先執(zhí)行
線程的生命周期
2、實(shí)現(xiàn)Runnable:
- 定義一個類實(shí)現(xiàn)Runnable接口
- 在類1中重寫run()方法
- 創(chuàng)建類1的對象
- 創(chuàng)建Threa類的對象,把類1對象作為構(gòu)造方法的參數(shù)
- 啟動線程
代碼示例
public class RunnableDemo implements Runnable {
@Override
public void run() {
for (int i = 1;i < 100;i++){
System.out.println(i);
}
}
public static void main(String[] args) {
RunnableDemo runnableDemo = new RunnableDemo();
Thread thread1 = new Thread(runnableDemo,"線程1");
Thread thread2 = new Thread(runnableDemo,"線程2");
thread1.start();
thread2.start();
}
}
與Thread相比,實(shí)現(xiàn)Runnable的好處:
- 避免了Java單繼承額局限性
- 適合多個相同程序的代碼處理同一個資源的情況,把線程和程序的代碼、數(shù)據(jù)有效分離,較好的體現(xiàn)了面向?qū)ο蟮乃季S
3、實(shí)現(xiàn) Callable接口(Callable接口有返回值 Runnable接口無返回值),使用ExecutorService、Callable、Future實(shí)現(xiàn)有返回結(jié)果的多線程
示例代碼
public class CallableDemo implements Callable {
//1)重寫抽象方法call方法
@Override
public Integer call() throws Exception {
int result = new Random().nextInt(100);
System.out.println("執(zhí)行子線程完成某次計(jì)算,結(jié)果為"+result);
return result;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//2)創(chuàng)建Callable接口實(shí)現(xiàn)類對象
CallableDemo callableDemo = new CallableDemo();
//FutureTask實(shí)現(xiàn)了RunnableFuture接口,RunnableFuture繼承了Runnable接口,F(xiàn)utureTask接口就是Runnable接口的實(shí)現(xiàn)類
FutureTask<Integer> task = new FutureTask<>(callableDemo);
Thread thread1 = new Thread(task); //線程池:省去了創(chuàng)建線程、釋放線程的時間
//3)開啟新的線程
thread1.start();
System.out.println("result="+task.get());
}
}