Java是最早開始有併發的語言之一,再過去傳統多任務的模式下,人們發現很難解決一些更為複雜的問題,這個時候我們就有了併發. 引用 & 160; & 160; & 160; & 160;多線程比多任務更加有挑戰。多線程是在同一個程式內部並行執行,因此會對相同的記憶體空間進行併發讀寫操作。這可能是在單線程 ...
Java是最早開始有併發的語言之一,再過去傳統多任務的模式下,人們發現很難解決一些更為複雜的問題,這個時候我們就有了併發.
引用
多線程比多任務更加有挑戰。多線程是在同一個程式內部並行執行,因此會對相同的記憶體空間進行併發讀寫操作。這可能是在單線程程式中從來不會遇到的問題。其中的一些錯誤也未必會在單CPU機器上出現,因為兩個線程從來不會得到真正的並行執行。然而,更現代的電腦伴隨著多核CPU的出現,也就意味著不同的線程能被不同的CPU核得到真正意義的並行執行。
那麼,要開始Java併發之路,就要開始從java線程開始說起.
本篇幅將是本系列博客的開山篇,也就是基礎線程的複習.
線程簡介
線程百科
線程,有時被稱為輕量級進程(Lightweight Process,LWP),是程式執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共用進程所擁有的全部資源。
線程優點
資源利用率更好
程式設計在某些情況下更簡單
程式響應更快
線程代價
設計更複雜
上下文切換的開銷上升
增加資源消耗
線程的實現方式
線程我們有不同的實現方式,生產環境中用到的也有所不同,那麼,我們先來通過Demo看一下每種實現方式的區別.
通過Thread 實現的線程
public class Demo1 {
public static void main(String args[]) {
Thread thread = Thread.currentThread();
System.out.println("當前線程:" + thread);
thread.setName("hyh thread");//修改線程名稱
System.out.println("修改名稱之後:" + thread);
try {
for (int a = 5; a > 0; a--) {
System.out.println(a);
thread.sleep(1000);
}
} catch (Exception e) {
System.out.println("出現異常");
}
}
通過集成Runnable介面實現
Demo2.class 清單:
public class Demo2 implements Runnable {
Thread t;
//空構造函數
Demo2() {
t = new Thread(this, "測試線程");
System.out.println("子線程" + t);
t.start();
}
public void run() {
try {
for (int a = 5; a > 0; a--) {
System.out.println("子線程" + a);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("異常");
}
System.out.println("退出子線程");
}
}
/**
* 主類
*/
class ThreadDemo {
public static void main(String args[]) {
new Demo2();//創建一個新線程
try {
for (int i = 5; i > 0; i--) {
System.out.println("主線程:" + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("主線程異常");
}
//主線程退出
System.out.println("主線程退出");
}
}
通過集成 Thread 重寫run方法實現
public class Demo3 extends Thread {
public Demo3() {
//創建新線程
super("線程Demo");
System.out.println("子線程:" + this);
start();
}
@Override
public void run() {
try {
for (int a = 5; a > 0; a--) {
System.out.println("子線程:" + a);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("子程式異常");
}
}
}
class MasterThread {
public static void main(String args[]) {
new Demo3();//創建新線程
try {
for (int i = 5; i > 0; i--) {
System.out.println("主線程:" + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("主程式異常");
}
System.out.println("主程式退出...");
}
}
三個線程的實現
在日常生產中,使用線程可以通過實現Runnable介面.下麵我們通過該方法實現簡單的三個線程Demo
結構: 創建一個Demo4類,另外一個主類MultThreadDemo.
清單:
public class Demo4 implements Runnable {
//全局變數
String name;
Thread thread;
//構造器
public Demo4(String th) {
name = th;
thread = new Thread(this, name);
System.out.println("新線程" + thread);
//開始線程
thread.start();
}
//重寫run方法
public void run() {
try {
for (int a = 5; a > 0; a--) {
System.out.println(name + ":" + a);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("異常");
}
System.out.println(name + "線程結束");
}
}
/**
* 測試類
*
* @author hyh
*/
class MultThreadDemo {
public static void main(String[] args) {
//創建三個線程
Demo4 thread_1 = new Demo4("線程一");
Demo4 thread_2 = new Demo4("線程二");
Demo4 thread_3 = new Demo4("線程三");
//查看狀態
System.out.println("線程一狀態:" + thread_1.thread.isAlive());
System.out.println("線程二狀態:" + thread_2.thread.isAlive());
System.out.println("線程三狀態:" + thread_3.thread.isAlive());
try {
System.out.println("等待其他線程結束");
//使用join確保主線程最後運行
thread_1.thread.join();
thread_2.thread.join();
thread_3.thread.join();
} catch (InterruptedException e) {
System.out.println("線程異常");
}
//查看狀態
System.out.println("線程一:" + thread_1.thread.isAlive());
System.out.println("線程二:" + thread_2.thread.isAlive());
System.out.println("線程三:" + thread_3.thread.isAlive());
}
}
到此,開山Demo完成.
本文源碼Github地址:
https://github.com/hanyahong/com-hanyahong-blog/tree/master/com-hanyahong-thread-1/src/main/java/com/hyh/thread
思考:進程與線程的比較
進程
資源分配的基本單位。
所有與該進程有關的資源,都被記錄在進程式控制制塊PCB中。
進程處理機的調度單位,擁有完整的虛擬地址空間。當進程發生調度時,不同的進程擁有不同的虛擬地址空間,而同一進程內的不同線程共用同一地址空間。
線程與資源分配無關,屬於某一個進程,並與其他線程共用進程資源。
線程只由相關堆棧(系統棧或用戶棧)寄存器和線程式控制製表TCB組成。寄存器可被用來存儲線程內的局部變數,但不能存儲其他線程的相關變數。
進程在多線程中,進程不是一個可執行的實體。
兩者比較:
調度和切換:線程上下文切換比進程上下文切換要快得多。
通信:進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變數)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。
地址空間和其它資源(如打開文件):進程間相互獨立,同一進程的各線程間共用。某進程內的線程在其它進程不可見。
(本篇完)
WeChat: wixf150
原創文章,轉發請註明出處:http://www.cnblogs.com/hyhnet/p/6250264.html
訪問獨立站點,獲得更好用戶體驗:http://www.hanyahong.com