最全面的java多執行緒用法解析,如果你對Java的多執行緒機制並沒有深入的研究,那麼本文可以幫助你更透徹地理解Java多執行緒的原理以及使用方法。
1.建立執行緒
在Java中建立執行緒有兩種方法:使用Thread類別和使用Runnable介面。使用Runnable介面時需要建立一個Thread實例。因此,無論是透過Thread類別或Runnable介面建立線程,都必須建立Thread類別或它的子類別的實例。 Thread建構子:
public Thread( );
public Thread(Runnable target);
public Thread(Stringname);
public Thread(Runnable target);
public Thread(ThreadGroup group, String name);
public Thread(ThreadGroup group, Runnable target, String name);
public Thread(ThreadGroup target, String 長度,
方法一:繼承Thread類別覆蓋run方法public class ThreadDemo1 { public static void main(String[] args){ Demo d = new Demo(); d.start(); for(int i=0;i<60;i++){ System.out.println(Thread.currentThread().getName()+i); } } } class Demo extends Thread{ public void run(){ for(int i=0;i<60;i++){ System.out.println(Thread.currentThread().getName()+i); } } }
方法二:
public class ThreadDemo2 { public static void main(String[] args){ Demo2 d =new Demo2(); Thread t = new Thread(d); t.start(); for(int x=0;x<60;x++){ System.out.println(Thread.currentThread().getName()+x); } } } class Demo2 implements Runnable{ public void run(){ for(int x=0;x<60;x++){ System.out.println(Thread.currentThread().getName()+x); } } }
2.執行緒的生命週期
與人有生老病死一樣,執行緒也同樣要經歷開始(等待)、運行、掛起和停止種不同的狀態。這四種狀態都可以透過Thread類別中的方法進行控制。下面給出了Thread類別中和這四種狀態相關的方法。
// 開始執行緒
publicvoid start( );publicvoid run( );
// 掛起與喚醒執行緒publicvoid resume( ); // 不建議使用publiccoppublicvoid resume( ); // 不建議使用publiccoppublicvoid; sleep(long millis);
publicstaticvoid sleep(long millis, int nanos);
// 終止線程
publicvoid stop( ); // 不建議使用
publicvoid interrupt(public) 得到執行緒;
publicboolean isInterrupted( );
publicstaticboolean interrupted( );
// join方法
publicvoid join( ) throws InterruptedException;
在建立後並沒有馬上執行執行方法中的程式碼。當執行緒處於等待狀態時,可以透過Thread類別的方法來設定執行緒不各種屬性,如執行緒的優先權(setPriority)、執行緒名(setName)和執行緒的類型(setDaemon)等。
當呼叫start方法後,執行緒開始執行run方法中的程式碼。執行緒進入運行狀態。可以透過Thread類別的isAlive方法來判斷執行緒是否處於運行狀態。當執行緒處於運行狀態時,isAlive傳回true,當isAlive回傳false時,可能執行緒處於等待狀態,也可能處於停止狀態。下面的程式碼示範了執行緒的建立、運行和停止三個狀態之間的切換,並輸出了對應的isAlive回傳值。
一但執行緒開始執行run方法,就會一直到這個run方法執行完成這個執行緒才退出。但在執行緒執行的過程中,可以透過兩個方法使執行緒暫時停止執行。這兩個方法是suspend和sleep。使用suspend掛起執行緒後,可以透過resume方法喚醒執行緒。而使用sleep讓執行緒休眠後,只能在設定的時間後讓執行緒處於就緒狀態(在執行緒休眠結束後,執行緒不一定會馬上執行,只是進入了就緒狀態,等待系統進行調度)。
在使用sleep方法時有兩點需要注意:
1. sleep方法有兩個重載形式,其中一個重載形式不僅可以設毫秒,而且還可以設納秒(1,000,000納秒等於1毫秒) 。但大多數作業系統平台上的Java虛擬機都無法精確到奈秒,因此,如果對sleep設定了奈秒,Java虛擬機將取最接近這個值的毫秒。
2. 使用sleep方法時必須使用throws或try{…}catch{…}。因為run方法無法使用throws,所以只能用try{…}catch{…}。當在執行緒休眠的過程中,使用interrupt方法中斷執行緒時sleep會拋出一個InterruptedException例外。 sleep方法的定義如下:
publicstaticvoid sleep(long millis) throws InterruptedException
publicstaticvoid sleep(long millis, int nanos) throws InterruptedException有三種方法可以使執行緒有三種方法可以終止執行緒。
1. 使用退出標誌,使執行緒正常退出,也就是當run方法完成後執行緒終止。
2. 使用stop方法強行終止執行緒(這個方法不建議使用,因為stop和suspend、resume一樣,也可能發生不可預料的結果)。
3. 使用interrupt方法中斷執行緒。
1. 使用退出標誌終止執行緒
当run方法执行完后,线程就会退出。但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){…}来处理。但要想使while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。下面给出了一个利用退出标志终止线程的例子。
join方法的功能就是使异步执行的线程变成同步执行。也就是说,当调用线程实例的start方法后,这个方法会立即返回,如果在调用start方法后后需要使用一个由这个线程计算得到的值,就必须使用join方法。如果不使用join方法,就不能保证当执行到start方法后面的某条语句时,这个线程一定会执行完。而使用join方法后,直到这个线程退出,程序才会往下执行。下面的代码演示了join的用法。
3.多线程安全问题
问题原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行,导致共享数据的错误。
解决办法:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不执行。
同步代码块:
public class ThreadDemo3 { public static void main(String[] args){ Ticket t =new Ticket(); Thread t1 = new Thread(t,"窗口一"); Thread t2 = new Thread(t,"窗口二"); Thread t3 = new Thread(t,"窗口三"); Thread t4 = new Thread(t,"窗口四"); t1.start(); t2.start(); t3.start(); t4.start(); } } class Ticket implements Runnable{ private int ticket =400; public void run(){ while(true){ synchronized (new Object()) { try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(ticket<=0) break; System.out.println(Thread.currentThread().getName()+"---卖出"+ticket--); } } } }
同步函数
public class ThreadDemo3 { public static void main(String[] args){ Ticket t =new Ticket(); Thread t1 = new Thread(t,"窗口一"); Thread t2 = new Thread(t,"窗口二"); Thread t3 = new Thread(t,"窗口三"); Thread t4 = new Thread(t,"窗口四"); t1.start(); t2.start(); t3.start(); t4.start(); } } class Ticket implements Runnable{ private int ticket = 4000; public synchronized void saleTicket(){ if(ticket>0) System.out.println(Thread.currentThread().getName()+"卖出了"+ticket--); } public void run(){ while(true){ saleTicket(); } } }
同步函数锁是this 静态同步函数锁是class
线程间的通信
public class ThreadDemo3 { public static void main(String[] args){ class Person{ public String name; private String gender; public void set(String name,String gender){ this.name =name; this.gender =gender; } public void get(){ System.out.println(this.name+"...."+this.gender); } } final Person p =new Person(); new Thread(new Runnable(){ public void run(){ int x=0; while(true){ if(x==0){ p.set("张三", "男"); }else{ p.set("lili", "nv"); } x=(x+1)%2; } } }).start(); new Thread(new Runnable(){ public void run(){ while(true){ p.get(); } } }).start(); } } /* 张三....男 张三....男 lili....nv lili....男 张三....nv lili....男 */
修改上面代码
public class ThreadDemo3 { public static void main(String[] args){ class Person{ public String name; private String gender; public void set(String name,String gender){ this.name =name; this.gender =gender; } public void get(){ System.out.println(this.name+"...."+this.gender); } } final Person p =new Person(); new Thread(new Runnable(){ public void run(){ int x=0; while(true){ synchronized (p) { if(x==0){ p.set("张三", "男"); }else{ p.set("lili", "nv"); } x=(x+1)%2; } } } }).start(); new Thread(new Runnable(){ public void run(){ while(true){ synchronized (p) { p.get(); } } } }).start(); } } /* lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv 张三....男 张三....男 张三....男 张三....男 */
等待唤醒机制
/* *线程等待唤醒机制 *等待和唤醒必须是同一把锁 */ public class ThreadDemo3 { private static boolean flags =false; public static void main(String[] args){ class Person{ public String name; private String gender; public void set(String name,String gender){ this.name =name; this.gender =gender; } public void get(){ System.out.println(this.name+"...."+this.gender); } } final Person p =new Person(); new Thread(new Runnable(){ public void run(){ int x=0; while(true){ synchronized (p) { if(flags) try { p.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }; if(x==0){ p.set("张三", "男"); }else{ p.set("lili", "nv"); } x=(x+1)%2; flags =true; p.notifyAll(); } } } }).start(); new Thread(new Runnable(){ public void run(){ while(true){ synchronized (p) { if(!flags) try { p.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }; p.get(); flags =false; p.notifyAll(); } } } }).start(); } }
生产消费机制一
public class ThreadDemo4 { private static boolean flags =false; public static void main(String[] args){ class Goods{ private String name; private int num; public synchronized void produce(String name){ if(flags) try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.name =name+"编号:"+num++; System.out.println("生产了...."+this.name); flags =true; notifyAll(); } public synchronized void consume(){ if(!flags) try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("消费了******"+name); flags =false; notifyAll(); } } final Goods g =new Goods(); new Thread(new Runnable(){ public void run(){ while(true){ g.produce("商品"); } } }).start(); new Thread(new Runnable(){ public void run(){ while(true){ g.consume(); } } }).start(); } }
生产消费机制2
public class ThreadDemo4 { private static boolean flags =false; public static void main(String[] args){ class Goods{ private String name; private int num; public synchronized void produce(String name){ while(flags) try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.name =name+"编号:"+num++; System.out.println(Thread.currentThread().getName()+"生产了...."+this.name); flags =true; notifyAll(); } public synchronized void consume(){ while(!flags) try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"消费了******"+name); flags =false; notifyAll(); } } final Goods g =new Goods(); new Thread(new Runnable(){ public void run(){ while(true){ g.produce("商品"); } } },"生产者一号").start(); new Thread(new Runnable(){ public void run(){ while(true){ g.produce("商品"); } } },"生产者二号").start(); new Thread(new Runnable(){ public void run(){ while(true){ g.consume(); } } },"消费者一号").start(); new Thread(new Runnable(){ public void run(){ while(true){ g.consume(); } } },"消费者二号").start(); } } /* 消费者二号消费了******商品编号:48049 生产者一号生产了....商品编号:48050 消费者一号消费了******商品编号:48050 生产者一号生产了....商品编号:48051 消费者二号消费了******商品编号:48051 生产者二号生产了....商品编号:48052 消费者二号消费了******商品编号:48052 生产者一号生产了....商品编号:48053 消费者一号消费了******商品编号:48053 生产者一号生产了....商品编号:48054 消费者二号消费了******商品编号:48054 生产者二号生产了....商品编号:48055 消费者二号消费了******商品编号:48055 */
以上就是对Java 多线程的资料整理,后续继续补充相关知识,谢谢大家对本站的支持!
更多Java Thread多线程详解及用法解析相关文章请关注PHP中文网!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

Dreamweaver Mac版
視覺化網頁開發工具

禪工作室 13.0.1
強大的PHP整合開發環境

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器