JAVA多執行緒Thread VS Runnable詳解
要求
-
必備知識
本文要求基本瞭解JAVA程式設計知識。
-
開發環境
windows 7/EditPlus
-
演示地址
程序與執行緒
程序是程式在處理機中的一次執行。一個程序既包括其所要執行的指令,也包括了執行指令所需的系統資源,不同程序所佔用的系統資源相對獨立。所以程序是重量級的任務,它們之間的通訊和轉換都需要作業系統付出較大的開銷。
執行緒是程序中的一個實體,是被系統獨立排程和分派的基本單位。執行緒自己基本上不擁有系統資源,但它可以與同屬一個程序的其他執行緒共享程序所擁有的全部資源。所以執行緒是輕量級的任務,它們之間的通訊和轉換隻需要較小的系統開銷。
Java支援多執行緒程式設計,因此用Java編寫的應用程式可以同時執行多個任務。Java的多執行緒機制使用起來非常方便,使用者只需關注程式細節的實現,而不用擔心後臺的多工系統。
Java語言裡,執行緒表現為執行緒類。Thread執行緒類封裝了所有需要的執行緒操作控制。在設計程式時,必須很清晰地區分開執行緒物件和執行執行緒,可以將執行緒物件看作是執行執行緒的控制面板。線上程物件裡有很多方法來控制一個執行緒是否執行,睡眠,掛起或停止。執行緒類是控制執行緒行為的唯一的手段。一旦一個Java程式啟動後,就已經有一個執行緒在執行。可通過呼叫Thread.currentThread方法來檢視當前執行的是哪一個執行緒。
執行緒建立的兩種方法
JAVA中建立執行緒可以通過繼承Thread類和實現Runnable介面來建立一個執行緒。Runnable方式可以避免Thread 方式由於JAVA單繼承特性帶來的缺陷。Runnable的程式碼可以被多個執行緒(Thread例項)共享,適合於多個執行緒處理同一資源的情況。
-
繼承Thread類
class MyThread extends Thread{ ..... @Override public void run(){ } } MyThread mt=new MyThread(); mt.start();
-
實現Runnable介面
class MyThread implements Runnable{ .... @Override public void run(){ } } MyThread mt=new MyThread(); Thread td=new Thread(mt); sd.start();
Thread&Runnable分別模擬賣火車票
-
Thread方式
class MyThread extends Thread { private int ticketsCont=5; //一共有5張火車票 private String name; //視窗, 也即是執行緒的名字 public MyThread(String name){ this.name=name; } @Override public void run(){ while(ticketsCont>0){ ticketsCont--; //如果還有票,就賣掉一張票 System.out.println(name+"賣掉了1張票,剩餘票數為:"+ticketsCont); } } } public class TicketsThread { public static void main(String args[]){ //建立三個執行緒,模擬三個視窗賣票 MyThread mt1=new MyThread("視窗1"); MyThread mt2=new MyThread("視窗2"); MyThread mt3=new MyThread("視窗3"); //啟動三個執行緒,也即是視窗,開始賣票 mt1.start(); mt2.start(); mt3.start(); } }
-
Runnable方式
class MyThread2 implements Runnable { private int ticketsCont=1000; //一共有5張火車票 @Override public void run(){ while(true){ synchronized(this){ if(ticketsCont<=0){ break; } ticketsCont--; //如果還有票,就賣掉一張票 System.out.println(Thread.currentThread().getName()+"賣掉了1張票,剩餘票數為:"+ticketsCont); /*try{ Thread.sleep(50); //通過阻塞程式來檢視效果 } catch(Exception e){ System.out.println(e); }*/ } } } /*@Override //不加同步鎖 public void run(){ while(ticketsCont>0){ ticketsCont--; //如果還有票,就賣掉一張票 System.out.println(Thread.currentThread().getName()+"賣掉了1張票,剩餘票數為:"+ticketsCont); } }*/ } public class TicketsRunnable { public static void main(String args[]){ MyThread2 mt=new MyThread2(); //建立三個執行緒來模擬三個售票視窗 Thread th1=new Thread(mt,"視窗1"); Thread th2=new Thread(mt,"視窗2"); Thread th3=new Thread(mt,"視窗3"); //啟動三個執行緒,也即是三個視窗,開始賣票 th1.start(); th2.start(); th3.start(); } }
執行緒的生命週期
- 建立:新建一個執行緒物件,如Thread thd=new Thread()
- 就緒:建立了執行緒物件後,呼叫了執行緒的start()方法(此時執行緒知識進入了執行緒佇列,等待獲取CPU服務 ,具備了執行的條件,但並不一定已經開始運行了)
- 執行:處於就緒狀態的執行緒,一旦獲取了CPU資源,便進入到執行狀態,開始執行run()方法裡面的邏輯
- 終止:執行緒的run()方法執行完畢,或者執行緒呼叫了stop()方法,執行緒便進入終止狀態
- 阻塞:一個正在執行的執行緒在某些情況系,由於某種原因而暫時讓出了CPU資源,暫停了自己的執行,便進入了阻塞狀態,如呼叫了sleep()方法
執行緒的分類
- 使用者執行緒:執行在前臺,執行具有的任務程式的主執行緒,連線網路的子執行緒等都是使用者執行緒
- 守護執行緒:執行在後頭,為其他前臺執行緒服務。一旦所有使用者執行緒都結束執行,守護執行緒會隨JVM一起結束工作。可以通過呼叫Thread類的setDaemon(true)方法來設定當前的執行緒為守護執行緒,該方法必須在start()方法之前呼叫,否則會丟擲 IllegalThreadStateException異常。在守護執行緒中產生的新執行緒也是守護執行緒。不是所有的任務都可以分配給守護執行緒來執行,比如讀寫操作或者計算邏輯。
守護執行緒測試案例
場景:一個主執行緒,一個守護執行緒,守護執行緒會在很長一段時間內向本地檔案中寫入資料,主執行緒進入阻塞狀態等待使用者的輸入,一旦確認了使用者的輸入阻塞就會解除掉,主執行緒繼續執行直到結束,守護執行緒也會隨虛擬機器一同結束。
import java.io.*; import java.util.Scanner; class Daemon implements Runnable { @Override public void run(){ System.out.println("進入守護執行緒"); try{ writeToFile(); } catch(Exception e){ e.printStackTrace(); } System.out.println("退出守護執行緒"); } private void writeToFile() throws Exception{ File filename=new File("F:/慕課網(imooc)/細說多執行緒之Thread VS Runnable/daemon.txt"); OutputStream os=new FileOutputStream(filename,true); int count=0; while(count<999){ os.write(("\r\nword"+count).getBytes()); System.out.println("守護執行緒"+Thread.currentThread().getName()+"向檔案中寫入word"+count++); Thread.sleep(1000); } } } public class DaemonThreadDemo { public static void main(String args[]){ System.out.println("進入主執行緒"+Thread.currentThread().getName()); Daemon daemonThread=new Daemon(); Thread thread =new Thread(daemonThread); thread.setDaemon(true); thread.start(); Scanner sc=new Scanner(System.in); sc.next(); System.out.println("退出主執行緒"+Thread.currentThread().getName()); } }
測試結果
使用jstack生成執行緒快照
jstack工具到jdk安裝目錄bin資料夾下。jstack能生成JVM當前時刻執行緒的快照(threaddump, 即當前程序中所有執行緒的資訊)。幫助定位程式問題出現的原因,如長時間停頓、CPU佔用率過高等。
使用方法
jstack [-l] <pid> : [-l]可有可無,表示關於鎖的二位資訊;<pid>表示程序ID。
總結
建議使用Runnable這種方式建立執行緒。 程式中的同一資源指的是同一個Runnable物件。安全的賣票程式中需要加入同步synchronized。
如以上文章或連結對你有幫助的話,別忘了在文章結尾處輕輕點選一下 “還不錯”按鈕或到頁面右下角點選 “贊一個” 按鈕哦。你也可以點選頁面右邊“分享”懸浮按鈕哦,讓更多的人閱讀這篇文章。
相關推薦
JAVA多執行緒Thread VS Runnable詳解
要求 必備知識 本文要求基本瞭解JAVA程式設計知識。 開發環境 windows 7/EditPlus 演示地址 原始檔 程序與執行緒 程序是程式在處理機中的一次執行。一個程序既包括其所要執行的指令,也包括了執行指令所需的系統資源,不同程序所
java多執行緒Thread與Runnable的區別與使用深入理解
首先,多執行緒的實現方式兩種:一種是繼承Thread類,另一種是實現Runnable介面。 那麼這兩種方法的區別何在?該如何選擇? 第一:他們之間的關係 檢視J2EE的API看到 Thread類中: public class Thread extends Objec
Java多執行緒Condition介面原理詳解
Condition介面提供了類似Object的監視器方法,與Lock配合可以實現等待/通知模式,但是這兩者在使用方式以及功能特性上還是有差別的 Condition介面詳解 Condition定義了等待/通知兩種型別的方法,當前執行緒呼叫這些方法時,需要提前獲
Java多執行緒同步和非同步詳解
1. 多執行緒併發時,多個執行緒同時請求同一資源,必然導致此資源的資料不安全。 2. 執行緒池 在WEB服務中,對於web伺服器的響應速度必須儘可能的快,這就容不得在使用者提交請求按鈕後,再建立執行緒提供服務。為了減少使用者的等待時間,執行緒必須預先建立,放線上程池中,執行
入坑JAVA多執行緒併發(八)詳解ThreadLocal使用和原理
ThreadLocal是一個用於儲存多執行緒變數的類,它可以把執行緒與設定的值對應起來,因為它為變數在每個執行緒都建立了一個副本。訪問的時候每個執行緒只能訪問到自己的副本變數。 例項 看如下程式碼: public class Main {
Java 多執行緒之synchronized關鍵字詳解
package com.example; /** * Created by 晁東洋 on 2017/5/27. */ public class MyThreadClass { public static void main(String args[]){ Exampletest
java多執行緒與併發程式設計詳解
一、多執行緒1、作業系統有兩個容易混淆的概念,程序和執行緒。程序:一個計算機程式的執行例項,包含了需要執行的指令;有自己的獨立地址空間,包含程式內容和資料;不同程序的地址空間是互相隔離的;程序擁有各種資源和狀態資訊,包括開啟的檔案、子程序和訊號處理。執行緒:表示程式的執行流程
Java多執行緒-Thread.yield詳解
http://blog.csdn.net/dabing69221/article/details/17426953 Thread.yield( )方法: 使當前執行緒從執行狀態(執行狀態)變為可執行態(就緒狀態)。cpu會從眾多的可執行態裡選擇,也就是說,當前也就
java 多執行緒Thread類
Thread類之前在部落格簡單介紹了下,本篇重點介紹幾個常用方法: 先看構造方法: Thread() 建立新的執行緒物件 Thread(String name) 基於指定的名字建立一個執行緒物件 Thread(Runnable target)基於Runnable介面實現類的例項(可以
(CSDN遷移) JAVA多執行緒實現-實現Runnable介面
實現Runnable介面 implements Runnable 重寫run()方法 @Override public void run(){//TODO} 建立執行緒物件: Thread thread1 = new Thread(new Implement
java多執行緒Thread
認識多執行緒,首先要從程式是如何在CPU中進行排程說起,眾所周知,我們自己的筆記本中只有一個CPU,這個CPU在你電腦開機的時候開始就執行著許多程式,比如作業系統,可是一個CPU在某一單位時間只能執行一個程式,而電腦中這麼多的程式CPU是如何安排工作的呢?這就涉及到了併發的概念. 併發:有
java多執行緒-Thread的yield方法
yield表示當前執行緒申請交出執行權,但並不是一定會交出,依賴於系統的執行緒排程。 因此該方法並不穩定。 class Test { public static void main(String[] args) throws InterruptedException { Te
java多執行緒-Thread的sleep方法
public static native void sleep(long millis) throws InterruptedException; sleep是本地靜態方法。sleep的作用是讓執行緒進入TIME_WAITING狀態,引數是多少毫秒。 class Test { pu
Java多執行緒-----Thread常用方法
1.public Thread(Runnable target,String name) 建立一個有名稱的執行緒物件 package com.thread.mothed; public class ThreadMethod {
java多執行緒-Thread兩個執行緒交換資料Exchanger
/** * 2017-4-21 * author:饒為 * Administrator */package Thread;import java.util.concurrent.Exchanger;/** * 2017-4-21 * author:饒為 * Administrator */public cla
java多執行緒—Thread.Join()和Thread.Sleep()
其實我想要 一種美夢睡不著 一種心臟的狂跳 瓦解界線不被撂倒 奔跑 依靠 我心中最想要 看你看過的浪潮 陪你放肆地年少 ——林俊杰【偉大的渺小】 ------------
Java 多執行緒異常捕獲Runnable實現
1、背景: Java 多執行緒異常不向主執行緒拋,自己處理,外部捕獲不了異常。所以要實現主執行緒對子執行緒異常的捕獲。 2、工具: 實現Runnable介面的LayerInitTask類,ThreadException類,執行緒安全的Vect
Java 多執行緒——Thread類和Runable介面
在java中可有兩種方式實現多執行緒,一種是繼承Thread類,一種是實現Runnable介面; Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的 run()方法就可以實現多執行緒操作了,但是一個類只能繼承一個父類,這是此方法
多執行緒之Future使用詳解
什麼是Future Future是一個未來物件,裡面儲存這執行緒處理結果,它像一個提貨憑證,拿著它你可以隨時去提取結果 什麼時候使用 在兩種情況下,離開Future幾乎很難辦。 一種情況是拆分訂單,比如你的應用收到一個批量訂單,此時如果要求最快的處理訂單,那麼需要併發
Android 多執行緒之HandlerThread 完全詳解
之前對執行緒也寫過幾篇文章,不過倒是沒有針對android,因為java與android線上程方面大部分還是相同,不過本篇我們要介紹的是android的專屬類HandlerThread,因為HandlerThread在設定思想上還是挺值得我們學習的,那麼我們下面來