基礎(chǔ)的多進程
子線程的創(chuàng)建
進程:正在運行的一個程序QQ IDE 瀏覽器,系統(tǒng)會為這個進程分配獨立的內(nèi)存資源
線程:具體執(zhí)行任務(wù)的最小單位
一個進程最少擁有一個線程 (主線程 運行起來就執(zhí)行的線程)
線程之間是共享內(nèi)存資源的(進程申請的),線程之間可以通信(數(shù)據(jù)傳遞:多數(shù)為主線程和子線程)
每一個線程都有自己的運行回路(生命周期)
為什么需要創(chuàng)建子線程
- 如果在主線程存在比較耗時的操作:下載視頻 上傳文件 數(shù)據(jù)這些操作會阻塞主線程、后面的任務(wù)的任務(wù)必須等這些任務(wù)執(zhí)行完畢之后才能執(zhí)行
- 用戶體驗比較差
- 為了不阻塞主線程,后面的任務(wù)必須放到子線程中去處理
子線程的創(chuàng)建
1.寫一個類繼承于Thread 實現(xiàn)run方法
注意這里面的一些使用要點
join:讓當前這個線程阻塞 等join的線程執(zhí)行完畢再執(zhí)行 - setName:設(shè)置線程名稱
- getName:獲取線程名稱
- currentThread:獲取當前運行的線程對象
- start: 開啟任務(wù)
*NEW:新建 線程剛被創(chuàng)建好 - RUNNABLE:run runnable就緒狀態(tài)(只要搶到時間片就可以運行)
- BLOCKED:阻塞狀態(tài) sleep wait
- WAITING:等待wait
- TIMED WAITING
代碼實現(xiàn)
public static void main(String[] args) {
//main方法里面執(zhí)行的代碼 是在主線程里面執(zhí)行的
TestThread tt=new TestThread();
//設(shè)置線程的名稱
tt.setName("子線程1");
//開啟任務(wù)
tt.start();
}
class TestThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i + 1);
}
super.run();
}
}
2.實現(xiàn)Runnable接口 實現(xiàn)run方法
- a創(chuàng)建任務(wù)
- b使用Thread 為這個任務(wù)分配線程
- c開啟任務(wù) start
public static void main(String[] args) {
hmlTread pt = new hmlTread();
Thread t = new Thread(pt);
t.setName("子線程1");
t.start();
Thread t2 = new Thread(pt);
t2.setName("子線程2");
t2.start();
}
class hmlTread implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread()+":"+i);
}
}
}
線程安全
sychronized Lock 加鎖解鎖
* sychronized 同步監(jiān)聽器 需要一把鎖
* 任何一個對象都有自己的一把鎖
* 如果多個線程操作同一個代碼塊,并且需要同步
* 那么必須操作同一個對象/同一個對象的同一把鎖
* 1.同步代碼塊
* synchronize(監(jiān)聽器/對象/鎖){
* //需要同步的代碼塊
* }
鎖里面還有wait notifi notifiAll方法
就是指的阻塞、喚醒、喚醒全部
public static void main(String[] args) {
Ticket ticketCQ=new Ticket("重慶");
Thread t1=new Thread(ticketCQ);
t1.start();
Ticket ticketSH=new Ticket("上海");
Thread t2=new Thread(ticketSH);
t2.start();
}
class Ticket implements Runnable {
// //定義所有車票數(shù)量
public static int num = 100;
String name;
public Ticket(String name) {
this.name = name;
}
static final Object obj = new Object();
@Override
public void run() {
for (int i = 0; i < 100; i++) {
//判斷有沒有票
synchronized (obj) {
if (num > 0) {
System.out.println(name + "出票" + num);
num--;
obj.notify();
try {//當前線程等待
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//通知其它線程執(zhí)行
}
} else {
break;
}
}
}
}
}
2.ReentrantLock 可重入鎖
class Ticket implements Runnable {
// //定義所有車票數(shù)量
public static int num = 100;
String name;
public Ticket(String name) {
this.name = name;
}
static final Object obj = new Object();
static ReentrantLock lock=new ReentrantLock();
Condition condition=lock.newCondition();
//創(chuàng)建一個可重入的鎖
//
@Override
public void run() {
for (int i = 0; i < 100; i++) {
//判斷有沒有票
lock.lock();
if (num > 0) {
System.out.println(name + "出票" + num);
num--;
try {//當前線程等待
//obj.wait();
condition.signal();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//通知其它線程執(zhí)行
}
} else {
break;
}
lock.unlock();
}
}
}
synchronized其實和ReentrantLock實現(xiàn)的功能都差不多,都是加鎖,只不過可以使用的方法名不同而已。