程序、進程與線程
一:概念理解
程序:靜態的代碼,應用軟件執行的藍本
進程:程序的一次動態執行過程,對應了從代碼加載、執行至執行完畢的一個完整過程。
線程:比進程更小的執行單位,一個進程在執行過程中可以產生多個線程。
操作系統中使用分時管理各個進程,按時間片輪流執行每個進程。Java 的多線程就是在操作系統每次分時給 Java 程序一個時間片的 CPU 時間內,在若干獨立的可控制的線程之間進行切換。
Java 程序從 main 方法開始執行,當 JVM 加載代碼,發現 main 方法之後會啓動一個線程,這個線程是主線程,在 main 方法執行的過程中啓動的線程稱爲該程序的其他線程。當發現程序中包含主線程和其他線程時,JVM 會在主線程和其他線程之間輪流切換,保證每個線程都有機會使用 CPU 資源。
二:代碼分析
/**
* 分析程序:
* 1. JVM 首先將 CPU 資源分配給主線程,主線程在分配時執行了:
* //創建線程
* SpeakHello speakHello = new SpeakHello();
* SpeakNiHao speakNiHao = new SpeakNiHao();
* //啓動線程
* speakHello.start();
* speakNiHao.start();
* 2. 開始執行 for 循環,for 循環爲啥沒執行完呢?
* 主線程在使用 CPU 資源的時候執行了:
* speakHello.start();
* speakNiHao.start();
* 所以 JVM 知道已經有三個線程需要輪流切換使用 CPU 資源
* 3. speakNiHao.start() 的作用是通知 JVM: 咳咳咳,老子在等着你給我分配 CPU 資源
* @author guozhenZhao
* @date 2018年12月22日
*/
public class ThreadTest {
//主程序(主線程)
public static void main(String[] args) {
//創建線程
SpeakHello speakHello = new SpeakHello();
SpeakNiHao speakNiHao = new SpeakNiHao();
//啓動線程
speakHello.start();
speakNiHao.start();
for (int i = 1; i <= 20; i++) {
System.out.print("大家好"+i+" ");
}
}
}
//線程一
class SpeakHello extends Thread{
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
System.out.print("hello"+i+" ");
}
}
}
//線程二
class SpeakNiHao extends Thread{
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
System.out.print("您好"+i+" ");
}
}
}
synchronized關鍵字的理解
package com.zgz.multi.sync001;
/**
* 兩種情況:
* 一:
* 關鍵字synchronized取得的鎖都是對象鎖,而不是把一段代碼(方法)當作鎖
* 所以代碼中那個線程先執行synchronized關鍵字的方法,哪個線程就持有該方法所屬對象的鎖(lock)
* 二:
* 在靜態方法上加synchronized關鍵字,表示鎖定.class類,類一級別的鎖(獨佔這個類)
* @author guozhenZhao
* @date 2018年12月22日
*/
public class MultiThread {
private static int num = 0;
public synchronized void printNum(String tag) {
try {
if(tag.equals("a")) {
num = 100;
System.out.println("tag a, set num over");
Thread.sleep(1000);
}else {
num = 200;
System.out.println("tag b, set num over");
}
System.out.println("tag: "+tag+", num=" + num);
} catch (Exception e) {
e.printStackTrace();
}
}
//注意觀察run方法輸出順序
public static void main(String[] args) {
//兩個不同的對象
final MultiThread m1 = new MultiThread();
final MultiThread m2 = new MultiThread();
//創建線程t1、t2
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.printNum("a");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m2.printNum("b");
}
});
//通知jvm,有線程在等待執行
t1.start();
t2.start();
}
}