Java並發編程(一)
1、定義
線程是現代操作系統調用的最小單位,也叫輕量級進程,在一個進程裏可以創建多個線程,這些線程都擁有各自的計數器、堆棧和局部變量等屬性,並且能夠訪問共享的內存變量。
2、一個普通的java程序中包含哪些線程
下面是在jdk1.8.0_60環境下的代碼輸出。
1 import java.lang.management.ManagementFactory;2 import java.lang.management.ThreadInfo; 3 import java.lang.management.ThreadMXBean; 4 5 public class MultiThread { 6 public static void main(String[] args) { 7 // 獲取java線程管理MXBean 8 ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); 9 ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); 10 // 遍歷線程信息,僅打印線程ID和線程名稱信息 11 for (ThreadInfo threadInfo : threadInfos) { 12 System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName()); 13 } 14 System.out.println(System.getProperty("java.version")); 15 } 16 }
輸出結果:
[5] Attach Listener //負責接收到外部的命令,對該命令進行執行然後把結果返回給發送者 [4] Signal Dispatcher //分發處理發送給JVM信號的線程 [3] Finalizer //調用對象finalize方法的線程 [2] Reference Handler //清除Reference的線程 [1] main //main線程,用戶程序入口 1.8.0_60 //jdk版本號
3、優先級
在Java線程中,通過一個整型成員變量priority來控制優先級,優先級的範圍從1-10,在線程構建的時候可以通過setPriority(int)方法來修改優先級,默認優先級是5,優先級高的線程分配時間片的數量要多余優先級低的線程。在不同的JVM以及操作系統上,線程規劃會存在差異,有些操作系統甚至會忽略線程優先級的設定。
4、優先級例子
我的電腦是win7,64,jdk1.8,輸出結果表明優先級生效了。
1 package thread; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.concurrent.TimeUnit; 6 7 public class Priority { 8 private static volatile boolean notStart = true; 9 private static volatile boolean notEnd = true; 10 11 static class Job implements Runnable{ 12 private int priority; 13 private long jobCount; 14 public Job(int priority){ 15 this.priority = priority; 16 } 17 @Override 18 public void run() { 19 while(notStart){ 20 Thread.yield(); 21 } 22 while(notEnd){ 23 Thread.yield(); 24 jobCount++; 25 } 26 } 27 } 28 public static void main(String[] args) throws InterruptedException { 29 List<Job> jobs = new ArrayList<Job>(); 30 for(int i = 0; i < 10; i++){ 31 //設置優先級 32 int priority = i < 5 ? Thread.MIN_PRIORITY:Thread.MAX_PRIORITY; 33 Job job = new Job(priority); 34 jobs.add(job); 35 Thread thread = new Thread(job,"Thread:" + i); 36 thread.setPriority(priority); 37 thread.start(); 38 } 39 notStart = false; 40 TimeUnit.SECONDS.sleep(2); 41 notEnd = false; 42 for(Job job : jobs){ 43 System.out.println("Job Priority : " + job.priority 44 + ", Count : " + job.jobCount); 45 } 46 } 47 }
輸出結果
1 Job Priority : 1, Count : 6607305 2 Job Priority : 1, Count : 3393520 3 Job Priority : 1, Count : 11684488 4 Job Priority : 1, Count : 8878447 5 Job Priority : 1, Count : 6607130 6 Job Priority : 10, Count : 12661281 7 Job Priority : 10, Count : 12467001 8 Job Priority : 10, Count : 12306292 9 Job Priority : 10, Count : 12425011 10 Job Priority : 10, Count : 12817522
5、線程的狀態
java線程在運行的生命周期中可能處於一下6種不同的狀態,某一刻只能是其中的一個狀態。
NEW:初始狀態,線程被構建,但是還沒有調用start()方法;
RUNNABLE:運行狀態,java線程將操作系統中的就緒和運行兩種狀態籠統地稱作“運行中”;
BLOCKED:阻塞狀態,表示線程阻塞於鎖;
WAITING:等待狀態,表示線程進入等待狀態,進入該狀態表示當前線程需要等待其他線程做出一些特定動作(通知或中斷);
TIME_WATING:超時等待狀態,該狀態不同於WAITING,它是可以在指定的時間自行返回的;
TERMINATED:終止狀態,表示當前線程已經執行完畢。
6、啟動和終止線程
構造線程:一個新構造的線程對象是由其parent線程來進行空間分配的,而child線程繼承了parent是否為Daemon(守護線程)、優先級和加載資源的contextClassLoader以及可繼承的ThreadLocal,同時還會分配一個唯一的ID來標識這個child線程。
啟動線程:調用start()方法,其含義是:當前線程(即parent線程)同步告知Java虛擬機,只要縣城規劃器空閑,應立即啟動調用start()方法的線程。
過期的suspend()、resume()、stop():不建議使用,以suspend方法為例,在調用後,線程不會釋放已經占有的資源(比如鎖),而是占有著資源進入睡眠狀態,這樣容易引起死鎖問題。同樣,stop方法在終結一個線程時不會保證線程資源正常釋放,通常是沒有給予線程完成資源釋放工作的機會,因此會導致程序可能工作在不確定狀態下。
Java並發編程(一)