JAVA中的執行緒 和 程序
首先了解一些基本知識
執行緒
執行緒,有時被稱為輕量程序(Lightweight Process,LWP),是程式執行流的最小單元。一個標準的執行緒由執行緒ID,當前指令指標(PC),暫存器集合和堆疊組成。另外,執行緒是程序中的一個實體,是被系統獨立排程和分派的基本單位,執行緒自己不擁有系統資源,只擁有一點兒在執行中必不可少的資源,但它可與同屬一個程序的其它執行緒共享程序所擁有的全部資源。一個執行緒可以建立和撤消另一個執行緒,同一程序中的多個執行緒之間可以併發執行。由於執行緒之間的相互制約,致使執行緒在執行中呈現出間斷性。執行緒也有就緒、阻塞和執行三種基本狀態。就緒狀態是指執行緒具備執行的所有條件,邏輯上可以執行,在等待處理機;執行狀態是指執行緒佔有處理機正在執行;阻塞狀態是指執行緒在等待一個事件(如某個訊號量),邏輯上不可執行。每一個程式都至少有一個執行緒,若程式只有一個執行緒,那就是程式本身。
執行緒是程式中一個單一的順序控制流程。程序內有一個相對獨立的、可排程的執行單元,是系統獨立排程和分派CPU的基本單位指令執行時的程式的排程單位。在單個程式中同時執行多個執行緒完成不同的工作,稱為多執行緒。
程序
狹義定義:程序就是程式的執行過程。
程序是一個具有一定獨立功能的程式關於某個資料集合的一次執行活動。它是作業系統動態執行的基本單元,在傳統的作業系統中,程序既是基本的分配單元,也是基本的執行單元。
程序的概念主要有兩點:第一,程序是一個實體。每一個程序都有它自己的地址空間,一般情況下,包括文字區域(text region)、資料區域(data region)和堆疊(stack region)。文字區域儲存處理器執行的程式碼;資料區域儲存變數和程序執行期間使用的動態分配的記憶體;堆疊區域儲存著活動過程呼叫的指令和本地變數。第二,程序是一個“執行中的程式”。程式是一個沒有生命的實體,只有處理器賦予程式生命時,它才能成為一個活動的實體,我們稱其為程序。
程序是作業系統中最基本、重要的概念。是多道程式系統出現後,為了刻畫系統內部出現的動態情況,描述系統內部各道程式的活動規律引進的一個概念,所有多道程式設計作業系統都建立在程序的基礎上。
進入正題
一.執行緒的建立方式
方式一:繼承Thread並重寫run方法
package thread; /** * 執行緒有兩種建立方式: * 方式一:繼承Thread並重寫run方法,並在run方法中新增執行緒要執行的任務程式碼。 * 1:由於java繼承是單繼承的,這就導致了繼承了Thread就不能繼承其它類,在實際開發中有諸多不便。 * 2:定義執行緒的同時在run方法中定義了執行緒要執行的任務,這就導致了執行緒和執行的任務有一個必然的耦合關係,不利於執行緒的重用。 * @author soft01 * */ public class ThreadDemo01 { public static void main(String[]args) { Thread t1=new MyThread1(); Thread t2=new MyThread2(); Thread t3=new MyThread3(); /** * 需要注意,啟動執行緒要排程的是執行緒的start方法,而不是直接呼叫run方法 * 當start方法呼叫之後,執行緒納入執行緒排程,一旦執行緒獲取cpu時間片段後,執行緒會自動呼叫run方法 * */ t1.start();//執行緒沒有先後順序,是排程器隨機排程的 t2.start();//start()方法啟動執行緒 t3.start(); } } /** * 執行緒和執行緒執行的任務存在強 耦合 關係;擴充套件性不好,不靈活,重複性差 */ class MyThread1 extends Thread{ public void run() { for(int i=0;i<1000;i++) { System.out.println("劫"); } } } class MyThread2 extends Thread{ public void run() { for(int i=0;i<1000;i++) { System.out.println("均衡存乎萬物之間"); } } } class MyThread3 extends Thread{ public void run() { for(int i=0;i<100;i++) { System.out.println("傳統是智慧的糟粕"); } } }
方式二:實現Runnable介面單獨定義
package thread;
/**
* 第二種建立執行緒的方式:
* 實現Runnable介面單獨定義 執行緒任務
* 這樣 執行緒和 執行緒內的方法就解 耦合 了;執行緒就可以繼承別的類
* @author soft01
*
*/
public class ThreadDemo02 {
public static void main(String[] args) {
//例項化執行緒任務
Runnable r1=new MyRunnable1();
Runnable r2=new MyRunnable2();
//例項化執行緒
Thread t1=new Thread(r1);
Thread t2=new Thread(r2);
t1.start(); //執行緒沒有先後,而是隨機的
t2.start();
t1.yield();
}
}
class MyRunnable1 implements Runnable{
public void run() {
for(int i=0;i<100;i++) {
System.out.println("搖搖晃晃");
}
}
}
class MyRunnable2 implements Runnable{
public void run() {
for(int i=0;i<100;i++) {
System.out.println("搖還是不搖");
}
}
}
附加小點心:匿名內部類建立執行緒
package thread;
/**
* 使用匿名內部類的建立形式完成執行緒的兩種方式建立
* @author soft01
*
*/
public class ThreadDemo03 {
public static void main(String[] args) {
//繼承Thread重寫run方法:
Thread t1=new Thread() {
public void run() {
for(int i=0;i<100;i++) {
System.out.println("諾克薩斯");
}
}
}; //加;號,匿名內部類,這是一行語句
//實現Runnable介面:
Runnable r2=new Runnable() {
public void run() {
for(int i=0;i<100;i++) {
System.out.println("比爾");
}
}
};
Thread t2=new Thread(r2);
t1.start();
t2.start();
}
}
二.執行緒的資訊
package thread;
public class Thread_info {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread main=Thread.currentThread();
//獲取執行緒名字
String name=main.getName();
System.out.println("name:"+name);
//獲取執行緒唯一標識
long id=main.getId();
System.out.println("id:"+id);
//獲取執行緒的優先順序
int priority=main.getPriority();
System.out.println("priority:"+priority);
//是否處於活動狀態
boolean isAlive=main.isAlive();
System.out.println("isAlive:"+isAlive);
//是否為守護執行緒
boolean isDaemon=main.isDaemon();
System.out.println("isDaemon:"+isDaemon);
//中斷
boolean isInterrupted=main.isInterrupted(); //正常中斷就是false 強制中斷就是true
System.out.println("isInterrput:"+isInterrupted);
//中斷執行緒 void
main.interrupt();
}
}
三.執行緒的優先順序
package thread;
/***
*執行緒的優先順序
*執行緒的併發執行是靠執行緒排程統一的,執行緒不能主動獲取CPU時間段,也不能決定時間片段的長短,只能被動地被分配。
*通過調整執行緒的優先級別可以最大程度地改善獲取CPU時間片的機率。
*理論上 執行緒優先級別越高的執行緒,獲取CPU時間片的次數越多,執行緒的優先順序由一個int值表示,範圍是1到10,
*1為最低優先順序,10為最高優先順序,5為預設值。
* @author soft01
*
*/
public class Thread_setPriority {
public static void main(String[]args) {
Thread min=new Thread() {
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("德瑪西亞萬歲");
}
}
};
Thread max=new Thread() {
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("諾克薩斯萬歲");
}
}
};
Thread norm=new Thread() {
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("均衡教派萬歲");
}
}
};
norm.setPriority(Thread.NORM_PRIORITY);
max.setPriority(Thread.MAX_PRIORITY);
min.setPriority(Thread.MIN_PRIORITY);
norm.start();
min.start();
max.start();
}
}
class MyThread01 extends Thread{
}
class MyThread02 extends Thread{
}
class MyThread03 extends Thread{
}
四.Thread.currentThread();
package thread;
/**
* 執行緒提供了一個靜態方法:
* static Thread currentThread()
* 該方法可以獲取執行這個方法的執行緒
*
* 獲取執行緒狀態資訊的
* @author soft01
*
*/
public class Thread_currentThread {
public static void main(String[] args) {//其實main方法就是一個執行緒執行的
// TODO Auto-generated method stub
Thread t0=Thread.currentThread();
System.out.println("執行該該方法的執行緒是:"+t0);
//main執行緒開始執行dosome方法
dosome();
//自定義執行緒
Thread t=new Thread("可以起執行緒名字") {
public void run() {
Thread t=Thread.currentThread();
System.out.println("執行run方法的執行緒是自定義執行緒:"+t);
dosome();
}
};
t.start();
//自定義執行緒2
Thread t1=new MyThread();
Thread.currentThread();
System.out.println("執行自定義執行緒2中run方法的執行緒是"+t1);
}
public static void dosome() {
Thread t=Thread.currentThread();
System.out.println("執行dosome方法的執行緒是:"+t);
}
}
class MyThread extends Thread{
public void run() {
System.out.println("nihao");
}
}
五.執行緒的其他方法
package thread;
/**
* Thread的靜態方法yield
* 該方法用於使當前執行緒主動讓出當此CPU時間片段回到Runnable狀態,等待分配時間片段
* @author soft01
*
*/
public class Thread_yield {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1=new Thread() {
public void run() {
for(int i=0;i<500;i++) {
try {
System.out.println("泰拉瑞亞"+i);
Thread.sleep(1000);
yield();
}catch(Exception e) {
e.printStackTrace();
}
}
}
};
Thread t2=new Thread() {
public void run() {
for(int i=0;i<500;i++) {
try {
System.out.println("鬼泣5 "+i);
Thread.sleep(10);
// yield();
}catch(Exception e) {
e.printStackTrace();
}
}
}
};
t1.start();
t2.start();
}
}
/**
* Thread 的靜態方法join
* 該方法用於等待當前執行緒結束。 需要結束的執行緒.join();
* 該方法宣告丟擲 InterruptException
* @author soft01
* 打斷,等待執行緒
*
*/
/**
* 執行緒1:生成一百個隨即數
* 執行緒2:負責排序(等待執行緒1的結束)
* @param args
*/
package thread;
import java.util.Arrays;
import java.util.Random;
public class Thread_join01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* 兩個執行緒共享同一個陣列,t1負責生成隨機數,t2負責排序,t2要等待t1的結束再繼續排序
*/
int[] ary=new int[100];
Thread t1=new ThreadA(ary);
Thread t2=new ThreadB(ary,t1);
t1.start();
t2.start();
}
}
//生成隨機數的執行緒
class ThreadA extends Thread{
int[]ary;
public ThreadA(int[]ary) {
this.ary=ary;
}
public void run() {
Random r=new Random();
for(int i=0;i<100;i++) {
ary[i]=r.nextInt(100);
}
//輸出陣列中的全部資料
System.out.println(Arrays.toString(ary));
}
}
//排序執行緒
class ThreadB extends Thread{
int[]ary;
Thread t1;
public ThreadB(int[]ary,Thread t1) {
this.ary=ary;
this.t1=t1;
}
public void run() {
//等待t1的結束 那就要先獲得t1的引用
try {
System.out.println("等待t1的結束!");
//等待t1結束
t1.join();
//t1正常結束,可以排序了
Arrays.sort(ary);
System.out.println(Arrays.toString(ary));
}catch(Exception e) {
//等待t1結束期間,被其他執行緒打斷,提前結束等待
e.printStackTrace();
}
}
}
package thread;
/**
* Thread提供了一個靜態方法:
* static void sleep(long ms)
* 該方法允許執行這個方法的執行緒進入阻塞狀態指定毫秒超時後執行緒會自動回到Runnable狀態等待繼續併發執行。
*
* 通常使用sleep方法控制週期性執行任務(如:定時器)
* 可以確保阻塞時間長,但是不能精確的時間間隔,因為sleep結束之後,是進入了Runnable狀態,等待cpu分配時間,而未進入running狀態
* @author soft01
*
*/
public class Thread_sleep {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("程式開始了!");
try {
Thread.sleep(5000);
}catch(InterruptedException e) {//執行緒阻塞中,被中斷,會丟擲異常;若未阻塞,中斷執行緒,則不會丟擲異常
e.printStackTrace();
}
System.out.println("程式結束了!");
}
}
六.守護執行緒
package thread;
/**
* 守護執行緒演示
*
* 守護執行緒在全部前臺執行緒結束後被結束,
* 不是立即結束,而是有少許延遲
* 理論:java程序在全部前臺執行緒結束時結束。
* 如果java執行緒沒有結束的話,則說明存在一個以上的沒有結束的前臺執行緒正在執行。
* @author soft01
*
*/
public class Thread_Daemon {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1=new Thread1();
Thread t2=new Thread2();
//將t2執行緒設定為守護執行緒
t2.setDaemon(true);
//啟動執行緒
t1.start();
t2.start();
}
}
/**
* 前臺執行緒
* @author soft01
*
*/
class Thread1 extends Thread{
public void run() {
for(int i=0;i<100;i++) {
System.out.println("前臺:"+i);
try {
Thread.sleep(10);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("前臺結束");
}
}
class Thread2 extends Thread{
public void run() {
for(int i=0;i<500;i++) {
System.out.println("後臺:"+i);
try {
Thread.sleep(10);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("後臺結束");
}
}
package thread;
//在內部類中運用守護執行緒
public class Thread_Daemon02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t=new Thread() {
public void run() {
for(int i=0;i<10;i++) {
System.out.println("中國!");
try {
Thread.sleep(1000);
}catch(Exception e) {
e.printStackTrace();
}
}
}
};
t.setDaemon(true);
}
}