Java是最早開始有并發(fā)的語言之一,再過去傳統(tǒng)多任務(wù)的模式下,人們發(fā)現(xiàn)很難解決一些更為復(fù)雜的問題,這個時候我們就有了并發(fā).
引用
? ? ? ?多線程比多任務(wù)更加有挑戰(zhàn)。多線程是在同一個程序內(nèi)部并行執(zhí)行,因此會對相同的內(nèi)存空間進行并發(fā)讀寫操作。這可能是在單線程程序中從來不會遇到的問題。其中的一些錯誤也未必會在單CPU機器上出現(xiàn)逸尖,因為兩個線程從來不會得到真正的并行執(zhí)行。然而,更現(xiàn)代的計算機伴隨著多核CPU的出現(xiàn)蚓庭,也就意味著不同的線程能被不同的CPU核得到真正意義的并行執(zhí)行。
? ? ? ?那么,要開始Java并發(fā)之路,就要開始從java線程開始說起.
? ? ? ?本篇幅將是本系列博客的開山篇,也就是基礎(chǔ)線程的復(fù)習.
線程簡介
線程百科
線程仅仆,有時被稱為輕量級進程(Lightweight Process器赞,LWP),是程序執(zhí)行流的最小單元墓拜。一個標準的線程由線程ID港柜,當前指令指針(PC),寄存器集合和堆棧組成。另外夏醉,線程是進程中的一個實體爽锥,是被系統(tǒng)獨立調(diào)度和分派的基本單位,線程自己不擁有系統(tǒng)資源畔柔,只擁有一點兒在運行中必不可少的資源氯夷,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。
線程優(yōu)點
資源利用率更好
程序設(shè)計在某些情況下更簡單
程序響應(yīng)更快
線程代價
設(shè)計更復(fù)雜
上下文切換的開銷上升
增加資源消耗
線程的實現(xiàn)方式
? ? ? ?線程我們有不同的實現(xiàn)方式,生產(chǎn)環(huán)境中用到的也有所不同,那么,我們先來通過Demo看一下每種實現(xiàn)方式的區(qū)別.
通過Thread 實現(xiàn)的線程
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("出現(xiàn)異常");
}
}
通過集成Runnable接口實現(xiàn)
Demo2.class 清單:
public class Demo2 implements Runnable {
Thread t;
//空構(gòu)造函數(shù)
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();//創(chuàng)建一個新線程
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方法實現(xiàn)
public class Demo3 extends Thread {
public Demo3() {
//創(chuàng)建新線程
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();//創(chuàng)建新線程
try {
for (int i = 5; i > 0; i--) {
System.out.println("主線程:" + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("主程序異常");
}
System.out.println("主程序退出...");
}
}
三個線程的實現(xiàn)
在日常生產(chǎn)中,使用線程可以通過實現(xiàn)Runnable接口.下面我們通過該方法實現(xiàn)簡單的三個線程Demo
結(jié)構(gòu): 創(chuàng)建一個Demo4類,另外一個主類MultThreadDemo.
清單:
public class Demo4 implements Runnable {
//全局變量
String name;
Thread thread;
//構(gòu)造器
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 + "線程結(jié)束");
}
}
/**
* 測試類
*
* @author hyh
*/
class MultThreadDemo {
public static void main(String[] args) {
//創(chuàng)建三個線程
Demo4 thread_1 = new Demo4("線程一");
Demo4 thread_2 = new Demo4("線程二");
Demo4 thread_3 = new Demo4("線程三");
//查看狀態(tài)
System.out.println("線程一狀態(tài):" + thread_1.thread.isAlive());
System.out.println("線程二狀態(tài):" + thread_2.thread.isAlive());
System.out.println("線程三狀態(tài):" + thread_3.thread.isAlive());
try {
System.out.println("等待其他線程結(jié)束");
//使用join確保主線程最后運行
thread_1.thread.join();
thread_2.thread.join();
thread_3.thread.join();
} catch (InterruptedException e) {
System.out.println("線程異常");
}
//查看狀態(tài)
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
思考:進程與線程的比較
進程
資源分配的基本單位靶擦。
所有與該進程有關(guān)的資源肠槽,都被記錄在進程控制塊PCB中。
進程處理機的調(diào)度單位奢啥,擁有完整的虛擬地址空間秸仙。當進程發(fā)生調(diào)度時,不同的進程擁有不同的虛擬地址空間桩盲,而同一進程內(nèi)的不同線程共享同一地址空間寂纪。
線程與資源分配無關(guān),屬于某一個進程赌结,并與其他線程共享進程資源捞蛋。
線程只由相關(guān)堆棧(系統(tǒng)棧或用戶棧)寄存器和線程控制表TCB組成柬姚。寄存器可被用來存儲線程內(nèi)的局部變量拟杉,但不能存儲其他線程的相關(guān)變量。
進程在多線程中量承,進程不是一個可執(zhí)行的實體搬设。
兩者比較:
調(diào)度和切換:線程上下文切換比進程上下文切換要快得多。
通信:進程間通信IPC撕捍,線程間可以直接讀寫進程數(shù)據(jù)段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助拿穴,以保證數(shù)據(jù)的一致性。
地址空間和其它資源(如打開文件):進程間相互獨立忧风,同一進程的各線程間共享默色。某進程內(nèi)的線程在其它進程不可見。
(本篇完)
WeChat: wixf150
原創(chuàng)文章狮腿,轉(zhuǎn)發(fā)請注明出處:http://www.cnblogs.com/hyhnet/p/6250264.html
訪問獨立站點,獲得更好用戶體驗:http://www.hanyahong.com