一:概念理解
多線程
程序:靜態的代碼,應用軟件執行的藍本
進程:程序的一次動態執行過程,對應了從代碼加載、執行至執行完畢的一個完整過程。
線程:比進程更小的執行單位,一個進程在執行過程當中能夠產生多個線程。jvm
操做系統中使用分時管理各個進程,按時間片輪流執行每一個進程。Java 的多線程就是在操做系統每次分時給 Java 程序一個時間片的 CPU 時間內,在若干獨立的可控制的線程之間進行切換。
Java 程序從 main 方法開始執行,當 JVM 加載代碼,發現 main 方法以後會啓動一個線程,這個線程是主線程,在 main 方法執行的過程當中啓動的線程稱爲該程序的其餘線程。當發現程序中包含主線程和其餘線程時,JVM 會在主線程和其餘線程之間輪流切換,保證每一個線程都有機會使用 CPU 資源。
二:代碼分析
ide
/** * 分析程序: * 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+" "); } } }
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(); //建立線程t一、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(); } }