執行緒及synchronized鎖的理解
阿新 • • 發佈:2018-12-23
程式、程序與執行緒
一:概念理解
程式:靜態的程式碼,應用軟體執行的藍本
程序:程式的一次動態執行過程,對應了從程式碼載入、執行至執行完畢的一個完整過程。
執行緒:比程序更小的執行單位,一個程序在執行過程中可以產生多個執行緒。
作業系統中使用分時管理各個程序,按時間片輪流執行每個程序。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(); } }