java并發(fā)編程專題(二)----如何創(chuàng)建并運行java線程
實現(xiàn)線程的兩種方式
上一節(jié)我們了解了關于線程的一些基本知識,下面我們正式進入多線程的實現(xiàn)環(huán)節(jié)。實現(xiàn)線程常用的有兩種方式,一種是繼承Thread類,一種是實現(xiàn)Runnable接口。當然還有第三種方式,那就是通過線程池來生成線程,后面我們還會學習,一步一個腳印打好基礎。
Runnable接口:
public interface Runnable { public abstract void run(); }
Thread類:
public class Thread implements Runnable { public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } @Override public void run() { if (target != null) { target.run(); } } }
上面為Thread類和Runnable類的源碼,我們可以看到Thread類也是實現(xiàn)了Runnable接口,即Thread是Runnable的實現(xiàn),那么他們到底在實現(xiàn)多線程上有什么區(qū)別呢?
Thread和Runnable解析:
(1)Runnable接口:
Runnable接口是java中線程的定義類。所有線程都是通過該接口來實現(xiàn),該接口中的run()方法為實現(xiàn)方法,即線程所要實現(xiàn)的內(nèi)容寫入該方法里面,當線程啟動時會調用該方法。
在大多數(shù)情況下,如果只想重寫run()方法而不重寫其他方法,應使用Runnable接口。
public class ThreadDemo3 { public static void main(String[] args) { //new了兩個線程對象——s1和s2 //其中兩個對象各對應一個內(nèi)存區(qū)域。線程運行過程中運行都是自己內(nèi)存塊中的數(shù)據(jù) Shop1 s1 = new Shop1("小武"); s1.start(); Shop1 s2 = new Shop1("小潘"); s2.start(); /* //實例化了兩個線程對象,所以分配了兩塊內(nèi)存空間 //執(zhí)行過程中操作的是自己的內(nèi)存空間 Shop2 s3 = new Shop2("小武"); s3.run(); Shop2 s4 = new Shop2("小潘"); s4.run(); //實際實例化了兩個線程對象 //所以同樣分配兩個內(nèi)存空間 Thread t1 = new Thread(new Shop2("小武")); t1.start(); Thread t2 = new Thread(new Shop2("小潘")); t2.start(); */ //創(chuàng)建了兩個線程對象,但是使用的是同一個對象——s6 Shop2 s5 = new Shop2("w"); Shop1 s6 = new Shop1("T"); Thread t3 = new Thread(s6); t3.start(); Thread t4 =new Thread(s6); t4.start(); } } /** * 武大郎賣燒餅(因為業(yè)務的拓展,現(xiàn)在可以實現(xiàn)多窗口的出售) * 要求:每天只賣10個 * */ class Shop1 extends Thread{ //private int count = 10; //使用靜態(tài)變量可以有效的實現(xiàn)資源共享(因為在內(nèi)存中只有一份count) private static int count = 10; public Shop1(String name) { super(name); } public void run(){ //判斷是否已經(jīng)賣完 while(count>0){ count--; System.out.println(this.getName() +"賣出了一個燒餅" + ",現(xiàn)在剩余" + count); } } } /** * 使用接口實現(xiàn)上面的代碼 * */ class Shop2 implements Runnable{ //私有變量,存儲剩余燒餅的個數(shù) private int count = 10; //存儲當前人的姓名 private String name=""; public Shop2(String name) { this.name = name; } /** * 實現(xiàn)銷售的方法 */ public void run(){ //判斷是否已經(jīng)賣完 while(count>0){ count--; System.out.println(Thread.currentThread().getId() + "、" + this.name +"賣出了一個燒餅" + ",現(xiàn)在剩余" + count); } } }
(2)Thread類:
Thread類是Runnable接口的實現(xiàn),jdk給我們提供了一個不用我們?nèi)ハ肴绾螌崿F(xiàn)線程的方式供我們使用。同樣你在繼承Thread類的時候也需要重寫run()方法來實現(xiàn)你想在線程中實現(xiàn)的內(nèi)容。
public class Test{ public static void main(String[] args) { //傳統(tǒng)方式——單任務方式 /* SimpleClass sc1 = new SimpleClass(); sc1.say("Mike"); SimpleClass sc2 = new SimpleClass(); sc2.say("Han Meimei"); */ //創(chuàng)建一個線程 ThreadClass tc1 = new ThreadClass("Mike"); //啟動線程 tc1.start(); //創(chuàng)建一個線程 ThreadClass tc2 = new ThreadClass("Han Meimei"); tc2.start(); } } } class SimpleClass{ public void say(String name){ while(true){ System.out.println("Hi,Im " + name); } } } class ThreadClass extends Thread{ public ThreadClass(String name) { super(name); } /** * 將父類(Thread)的run()方法進行重寫 * 在run()方法中包含了需要執(zhí)行的代碼 */ public void run(){ while(true){ System.out.println("Hi,Im " + this.getName() + "|" + this.getId() + "|" + this.getStackTrace()); } } }
Thread類中常用方法:
run():如果該線程時使用獨立的Runnable運行對象構造的,則調用該Runnable對象的run方法。否則,該方法不執(zhí)行任何操作并返回。
sleep(longmillls):在指定的毫秒數(shù)內(nèi)讓當前正在執(zhí)行的線程休眠(暫停執(zhí)行),此操作受到系統(tǒng)計時器和調度程序精度和準確性的影響 String
yield():暫停當前正在執(zhí)行的線程對象,并執(zhí)行其他線程 start():使該線程開始運行,java虛擬機再調用該線程的run方法
join():等待該線程結束
對比:
上面給出了Thread和Runnable的實現(xiàn),我們能看到在使用Runnable的方式實現(xiàn)線程的過程中:
Shop1 s6 = new Shop1("T"); Thread t3 = new Thread(s6); t3.start();
即把Runnable對象(實現(xiàn)了Runnable接口的對象)還是塞進了Thread中讓Thread來實現(xiàn)。那么我們可以new 多個Thread來實現(xiàn)同一個Runnbale對象,即實現(xiàn)了資源的共享,比如在售票系統(tǒng)中多名用戶對同一種票的搶購。另一方面,java是單繼承多實現(xiàn)的,如果我們使用Thread的話意味著該類只能繼承Thread,對于程序的擴展不利,而實現(xiàn)Runnbale接口則沒有這個顧慮。考慮程序的健壯性,我們應該盡量使用Runnable來實現(xiàn)我們的線程。
run和start
初學多線程我們總是分不清楚run()方法和start()方法的區(qū)別,其實我們再看一下上面Thread類的源碼就不難發(fā)現(xiàn)他們的用法是很容易區(qū)分的:
- run()方法是線程的實現(xiàn)方法,即你需要線程去做什么事情,那么這些實現(xiàn)的內(nèi)容寫在run()里面,當線程啟動時就會調用run()方法繼而實現(xiàn)run()內(nèi)部的代碼;
- start()方法是線程的啟動方法,即如果你new Thread()這樣并不算完。你還得new Thread().start()才算啟動這個線程,啟動完之后線程內(nèi)部會主動的調用run()方法執(zhí)行該線程的業(yè)務邏輯代碼。
以上就是java并發(fā)編程專題(二)----如何創(chuàng)建并運行java線程的詳細內(nèi)容,更多關于JAVA 創(chuàng)建并運行java線程的資料請關注腳本之家其它相關文章!
相關文章
spring boot 1.5.4 web容器定制(端口號等修改)方法
下面小編就為大家?guī)硪黄猻pring boot 1.5.4 web容器定制(端口號等修改)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06解決swaggerUI頁面沒有顯示Controller方法的坑
這篇文章主要介紹了解決swaggerUI頁面沒有顯示Controller方法的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Java前后端分離的在線點餐系統(tǒng)實現(xiàn)詳解
這是一個基于SpringBoot+Vue框架開發(fā)的在線點餐系統(tǒng)。首先,這是一個前后端分離的項目。具有一個在線點餐系統(tǒng)該有的所有功能,感興趣的朋友快來看看吧2022-01-01RabbitMQ實現(xiàn)延時消息的兩種方法實戰(zhàn)教程
這篇文章主要介紹了RabbitMQ實現(xiàn)延時消息的兩種方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09解決RestTemplate 的getForEntity調用接口亂碼的問題
這篇文章主要介紹了解決RestTemplate 的getForEntity調用接口亂碼的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08Maven中dependencyManagement管理項目依賴項
在開發(fā)?Java?項目時,管理和協(xié)調依賴項的版本號是一項重要而繁瑣的任務,本文主要介紹了Maven中dependencyManagement管理項目依賴項,具有一定的參考價值,感興趣的可以了解一下2024-01-01java數(shù)據(jù)結構與算法之雙向循環(huán)隊列的數(shù)組實現(xiàn)方法
這篇文章主要介紹了java數(shù)據(jù)結構與算法之雙向循環(huán)隊列的數(shù)組實現(xiàn)方法,結合實例形式分析了雙向循環(huán)隊列的原理與數(shù)組實現(xiàn)技巧,并附帶說明了該算法的用途,需要的朋友可以參考下2016-08-08