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