日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java获取其他类的线程,使用Java实现面向对象编程——第七章 多线程

發(fā)布時間:2024/9/18 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java获取其他类的线程,使用Java实现面向对象编程——第七章 多线程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1、進程:是指運行中的應(yīng)用程序,每個進程都有自己獨立的地址空間(內(nèi)存空間);

Eg:用戶點擊桌面的IE瀏覽器,就啟動了一個進程,操作系統(tǒng)就會為該進程分配獨立的地址空間。當(dāng)用戶再次點擊左面的IE瀏覽器,又啟動了一個進程,操作系統(tǒng)將為新的進程分配新的獨立的地址空間。目前操作系統(tǒng)都支持多進程。

◆注;用戶每啟動一個進程,操作系統(tǒng)就會為該進程分配一個獨立的內(nèi)存空間。

◆進程的特點:進程是系統(tǒng)運行程序的基本單位;

每一個程序都有自己獨立的一塊內(nèi)存空間、一組系統(tǒng)資源;

每一個進程的內(nèi)部數(shù)據(jù)和狀態(tài)都是完全獨立的;

2、線程:是進程中執(zhí)行元算的最小單位;可以完成一個獨立的順序控制流程;每個進程中,必須至少建立一個線程(主線程)來作為程序運行的入口點;

◆附加:

線程:是進程中的一個實體,是被系統(tǒng)獨立調(diào)度和分派的基本單位,線程自己不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源,

但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創(chuàng)建和撤消另一個線程,

同一進程中的多個線程之間可以并發(fā)執(zhí)行。

線程:

1、線程是輕量級的進程

2、線程沒有獨立的地址空間(內(nèi)存空間)

3、線程是由進程創(chuàng)建的(寄生在進程)

4、一個進程可以擁有多個線程-->這就是我們常說的多線程編程

線程的幾種狀態(tài):

a、創(chuàng)建狀態(tài)(new)

b、就緒狀態(tài)(Runnable)

c、運行狀態(tài)(Running)

d、阻塞狀態(tài)(Blocked)

e、死亡狀態(tài)(Dead)

3、多線程:如果在一個進程中同時運行了多個線程,用來完成不同的工作,則稱之為“多線程”;多個線程交替占用CPU資源,而非真正的并行執(zhí)行

●多線程好處:

a)充分利用CPU的資源

b)簡化編程模型

c)帶來良好的用戶體驗

4、JAVA中實現(xiàn)多線程:

●Thread類:Java提供了java.lang.Thread類支持多線程編程

◆ Thread類常用的方法:

構(gòu)造方法

說?????? 明

Thread()

分配新的Thread()對象

Thread(Runnable target)

分配新的Thread()對象。tarage為run()方法被調(diào)用的對象;

Thread(Runnable target,String nasme)

分配新的Thread()對象。tarage為run()方法被調(diào)用的對象;name為新線程的名稱

void run()

執(zhí)行任務(wù)操作的方法

void start()

使該線程開始執(zhí)行,JAVA虛擬機調(diào)用線程的run()方法

static void sleep(long millis)

在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行)

String getName()

返回線程的名字

Int getPriority()

返回線程的優(yōu)先級

void setPriority(int? newPriority)

更改線程的優(yōu)先級

static Thread currentThread()

返回當(dāng)前正在執(zhí)行的線程對象的引用

void join()

等待該線程終止

static void yield()

暫停當(dāng)前正在執(zhí)行的線程對象,并執(zhí)行其他線程

void interrupt()

中斷線程

boolean isAlive()

測試線程是否處于活動狀態(tài)

5、主線程:在JAVA線程啟動時,一個線程立即運行該線程稱為程序的主線程;每個線程至少有一個主線程;他是程序開始時就執(zhí)行;

◆?main()方法即為主線程入口

◆產(chǎn)生其他子線程的線程

◆必須最后完成執(zhí)行,因為它執(zhí)行各種關(guān)閉動作

★主線程可以由一個Thread對象控制,需要調(diào)用方法Thread.currentThread()獲得他的一個引用,

語法:static Thread currentThread()

Eg:

public static void main(String args[]) {

Thread t= Thread.currentThread(); //獲得主線程對象

System.out.println("當(dāng)前線程是: "+t.getName());

t.setName("MyJavaThread"); //設(shè)置線程名

System.out.println("當(dāng)前線程名是: "+t.getName()); //獲取線程名

}

◆在Java中創(chuàng)建線程的兩種方式:

★繼承java.lang.Thread類:繼承Thread類,并重寫run函數(shù)

★實現(xiàn)java.lang.Runnable接口:實現(xiàn)Runnable接口,并重寫run函數(shù)

◆使用線程的步驟:

★定義一個線程:同時指明這個線程所要執(zhí)行的代碼;

★創(chuàng)建線程對象;

★啟動線程

★終止線程

6、繼承Thread類創(chuàng)建線程:

●步驟:

★定義MyThread類繼承Thread類

★重寫run()方法,編寫線程執(zhí)行體

★創(chuàng)建線程對象,調(diào)用start()方法啟動線程

Eg:

public class MyThread extends Thread{? ? //繼承Thread類

//重寫run()方法

public void run(){? ? ? ? ?//run()方法中編寫線程執(zhí)行的代碼

for(int i=1;i<100;i++){

System.out.println(Thread.currentThread().getName()+":"+i);

}

}

}

public static void main(String[] args) {

MyThread thread = new MyThread();

thread.start(); //啟動線程

}

多個線程交替執(zhí)行,不是真正的“并行”

線程每次執(zhí)行時長由分配的CPU時間片長度決定

Eg:MyThread t1 = new MyThread();

MyThread t2 = new MyThread();

t1.start();

t2.start();

直接調(diào)用run()和start()區(qū)別:

start():啟動線程;

run():調(diào)用實例方法;

7、實現(xiàn)Runnable接口創(chuàng)建線程:

●步驟:

★定義MyRunnable類實現(xiàn)Runnable接口,并實現(xiàn)Runnable接口的run()方法在run()方法中實現(xiàn)輸出數(shù)據(jù);

★創(chuàng)建MyRunnable類的對象myRunnable;

★創(chuàng)建一個Thread類的對象myThread,將myRunnable對象作為Thread類構(gòu)造方法的參數(shù)傳入;

★調(diào)用myThread對象的start()方法啟動線程;

Eg:

public class MyRunnable implements Runnable{?? //實現(xiàn)Runnable接口

public void run(){

for(int i=1;i<100;i++){?????????? //?? run()方法中編寫線程執(zhí)行的代碼

System.out.println(Thread.currentThread().getName()+":"+i);

}

}

}

public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();? //創(chuàng)建線程對象

Thread myThread = new Thread(myRunnable);

thread.start(); ??//啟動線程

}

■用實現(xiàn)Runnable接口的特點:

1、用實現(xiàn)Runnable接口的方法創(chuàng)建對象可以避免java單繼承機制帶來的局限;

2、用實現(xiàn)Runnable接口的方法,可以實現(xiàn)多個線程共享同一段代碼(數(shù)據(jù));因此建議大家如果你的程序有同步邏輯需求,則使用Runnable的方法來創(chuàng)建線程。

比較兩種創(chuàng)建線程的方式:推薦使用實現(xiàn)Runnable接口方式創(chuàng)建線程

★繼承Thread類:

編寫簡單,可直接操作線程

適用于單繼承

★實現(xiàn)Runnable接口:

避免單繼承局限性

便于共享資源

附加:從java的設(shè)計來看,通過繼承Thread或者實現(xiàn)Runnable接口來創(chuàng)建線程本質(zhì)上沒有區(qū)別,

★從jdk幫助文檔我們可以看到Thread類本身就實現(xiàn)了Runnable接口,區(qū)別如下:

1、盡可能使用實現(xiàn)Runnable接口的方式來創(chuàng)建線程

2、在使用Thread的時候只需要new一個實例出來,調(diào)用start()方法即可以啟動一個線程,

如:????? Thread test=new Thread();

test.start();

3、在使用Runnable的時候需要先new一個實現(xiàn)Runnable的實例,之后用Thread調(diào)用,如:

Test implements Runnable

Test t=new Test();

Thread test=new Thread(t);

tset.start();

注意:不管是通過繼承Thread,還是通過實現(xiàn)Runnable接口創(chuàng)建線程,它們的一個對象只能啟動(即:start())一次。否則就會有(IllegaiIThreadStateException)異常拋出。

8、線程的狀態(tài):

1. 創(chuàng)建狀態(tài):在程序中用構(gòu)造方法創(chuàng)建了一個線程對象后,新的線程對象就處于創(chuàng)建狀態(tài),此時,它已經(jīng)獲取了相應(yīng)的資源,但還沒有處于可運行狀態(tài),這時可以通過Thread類的方法來設(shè)置線程對象的屬性,

如:設(shè)置線程名(setName())、設(shè)置線程優(yōu)先級(setPriority())等。

2. 就緒狀態(tài):線程創(chuàng)建之后,就可以通過調(diào)用start()方法啟動線程,即進入就緒狀態(tài)。此時,線程將進入線程隊列排隊,等待CPU資源,這表明它已經(jīng)具備了運行條件,在未獲得CPU資源時,仍不能真正執(zhí)行。

◆舉例來說,去醫(yī)院看病,某主任的專家號每天只有20個,掛上號的病人還需在分診處等待叫號。這里每個掛到專家號的病人可以看成一個就緒狀態(tài)的線程。

3.運行狀態(tài):當(dāng)就緒狀態(tài)的線程獲得CPU資源時,即可轉(zhuǎn)入運行狀態(tài),執(zhí)行的run()方法。對于只有一個CPU的機器而言,任何時刻只能有一個處于運行狀態(tài)的線程占用CPU,即獲得CPU資源。

◆延續(xù)上面醫(yī)院看病的例子,被叫到的病人才能真正就診,而每個主任專家在一個時刻只能為一個病人看病。

4. 阻塞狀態(tài):一個正在運行的線程因某種原因不能繼承運行時,進入阻塞狀態(tài)。阻塞狀態(tài)是一種“不可運行”的狀態(tài),而處于這種狀態(tài)的線程在得到一個特定的事件之后會轉(zhuǎn)回可運行狀態(tài)。

◆舉例來說,輪到小張看病了,醫(yī)生為查明原因要求他去做個化驗,醫(yī)生得到化驗結(jié)果后才能繼續(xù)診斷,如果把醫(yī)生給小張看病看作一個線程,該線程此時即處于阻塞狀態(tài)。

●可能使線程暫停執(zhí)行的條件:

?★線程優(yōu)先級比較低,因此它不能獲得CPU資源。

?★使用sleep()方法使線程休眠。

?★通過調(diào)用wait()方法,使線程等待。

?★通過調(diào)用yield()方法,線程顯式出讓CPU控制權(quán)。

?★線程由于等待一個文件I/O事件被阻塞。

5.死亡狀態(tài):一個線程的run()方法運行完畢,線程則進入死亡狀態(tài)。處于死亡狀態(tài)的線程不具有繼承運行的能力。

9、線程調(diào)度:線程調(diào)度指按照特定機制為多個線程分配CPU的使用權(quán);

●線程優(yōu)先級:線程靠搶CPU時間片而執(zhí)行,誰搶的多誰利用CPU的時間就多也就執(zhí)行得快。而決定這個爭搶能力的就是線程的優(yōu)先級;

●線程優(yōu)先級由1~10表示,1最低,10代表優(yōu)先級最高,默認(rèn)優(yōu)先級為5。

這些優(yōu)先級對應(yīng)一個Thread類的公用靜態(tài)常量;優(yōu)先級高的線程獲得CPU資源的概率較大;

線程的優(yōu)先級可以通過getPriority()方法獲取,setPriority(int grade)方法更改,參數(shù)表示要設(shè)置的優(yōu)先級,他必須是1~10的整數(shù);

MAX_PRORITY(最大優(yōu)先級),MIN_PRORITY(最小優(yōu)先級),NORM_PRORITY(默認(rèn)優(yōu)先級);

●線程調(diào)度的方法:

方法

說?????? 明

setPriority(int? newPriority)

更改線程的優(yōu)先級

static void sleep(long millis)

在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠

void join()

等待該線程終止

static void yield()

暫停當(dāng)前正在執(zhí)行的線程對象,并行其他線程

void interrupt()

中斷線程

boolean isAlive()

測試線程是否處于活動狀態(tài)

●線程休眠:在一個程序中一個線程允許進行暫時休眠,直接調(diào)用Thread sleep()方法即可實現(xiàn)線程的休眠;

sleep()方法語法定義:public static void sleep(long millis)

◆讓線程暫時睡眠指定時長,線程進入阻塞狀態(tài);

◆睡眠時間過后線程會再進入可運行狀態(tài);

Eg: public class Wait {

public static void bySec(long s) {

for (int i = 0; i < s; i++) {

System.out.println(i + 1 + "秒");

try {

Thread.sleep(1000); //線程休眠1秒

} catch (InterruptedException e) {

e.printStackTrace();

}}}}

★millis為休眠時長,以毫秒為單位

★調(diào)用sleep()方法需處理InterruptedException異常

●線程的強制運行:使當(dāng)前線程暫停執(zhí)行,等待其他線程結(jié)束后再繼續(xù)執(zhí)行本線程:

它的三個重載語法語法:

public final void join()

public final void join(long mills)

public final void join(long mills,int nanos)

◆millis:以毫秒為單位的等待時長

◆nanos:要等待的附加納秒時長

◆需處理InterruptedException異常

Eg:

public static void main(String[] args) {

Thread temp = new Thread(new MyThread());

temp.start();

for(int i=0;i<20;i++){

if(i==5){

try {

temp.join();//阻塞主線程,子線程強制執(zhí)行

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(Thread.currentThread().getName()+"運行:"+i);

}

//省略代碼……

}

結(jié)果:

●線程的禮讓:

◆yield()方法可以暫停當(dāng)前線程,允許其他具有相同優(yōu)先級的線程獲得運行機會;

◆該線程處于就緒狀態(tài),不轉(zhuǎn)為阻塞狀態(tài);此時系統(tǒng)選擇其他想相同或更高優(yōu)先級線程允許,若無其他相同或更高優(yōu)先級線程,則該線程繼續(xù)運行;

語法:public static void yield()

注:使用yield()的線程禮讓只是提供一種可能,但是不能保證一定會實現(xiàn)禮讓;

Eg:

10、線程的同步:當(dāng)多個線程共同操縱同一個共享資源的時候,會導(dǎo)致數(shù)據(jù)不一致的情況;當(dāng)多個線程共同操縱同一個共享資源的時候,一個線程未完成操作的時候,其他線程修改的數(shù)據(jù),會導(dǎo)致數(shù)據(jù)不安全的情況;

●多線程共享數(shù)據(jù)引發(fā)的問題:

●同步方法:

◆使用synchronized修飾的方法控制對類成員變量的訪問

語法:

◆synchronized(同步關(guān)鍵字)就是為當(dāng)前的線程聲明一個鎖

◆?syncObject為需同步的對象,通常為this,效果與同步方法相同

◆多個并發(fā)線程訪問同一資源的同步代碼塊時注意:

1、當(dāng)多個并發(fā)線程訪問同一個對象object的synchronized(this)同步代碼塊時,同一時刻只能有一個線程得到執(zhí)行,其他線程必須等待當(dāng)前線程執(zhí)行完畢之后才能執(zhí)行該代碼塊;

2、當(dāng)一個線程訪問一個object的synchronized(this)同步代碼塊時,其他線程對object中所有其他synchronized(this)同步代碼塊的訪問被阻塞,即該線程獲得這個object的對象鎖,其他線程對該object對象所有同步代碼部分的訪問被暫時阻塞;

3、當(dāng)一個線程訪問一個object的synchronized(this)同步代碼塊時,其他線程可以訪問該資源的非synchronized(this)同步代碼;

綜上所述:synchronized就是為當(dāng)前線程聲明一個鎖,獲得這個鎖的線程可以執(zhí)行代碼塊里的指令,其他的線程只能等待解鎖,然后才能執(zhí)行相同的操作;

◆同步代碼塊的應(yīng)用場景:假設(shè)某線程是非線程安全的,而且該類是第三方創(chuàng)建的或者是從內(nèi)置庫導(dǎo)入的,所以不能獲取他的源代碼,這樣,無法在相關(guān)方法前面加synchronized修飾符;

怎樣使該類的一個對象同步化?

解決方案:只需將對調(diào)用該方法的代碼放入一個synchronized塊內(nèi)就可以了;

◆關(guān)鍵代碼:

synchronized(同步對象){

//調(diào)用第三方非同步方法的代碼

}

11、線程安全的類型:

查看ArrayList類的add()方法定義:

public boolean add(E e) {

ensureCapacityInternal(size + 1);// 集合擴容,確保能新增數(shù)據(jù)

elementData[size++] = e;?? //在新增位置存放數(shù)據(jù)

return true;

}

ArrayList類的add()方法為非同步方法;

當(dāng)多個線程向同一個ArrayList對象添加數(shù)據(jù)時,可能出現(xiàn)數(shù)據(jù)不一致問題

ArrayList為非線程安全的類型

方法是否同步

效率比較

適合場景

線程安全(被synchronized修飾)

多線程并發(fā)共享資源

非線程安全

單線程

為達到安全性和效率的平衡,可以根據(jù)實際場景來選擇合適的類型

12、常用類型對比:

◆Hashtable&&HashMap

◆Hashtable:繼承關(guān)系,實現(xiàn)了Map接口,Hashtable繼承Dictionary類

特點:線程安全,效率較低

鍵和值都不允許為null

◆HashMap:繼承關(guān)系:實現(xiàn)了Map接口,繼承AbstractMap類

特點:?非線程安全,效率較高

鍵和值都允許為null

◆?StringBuffer? &&? StringBuilder:前者線程安全,后者非線程安全

13、附加1:死鎖問題:

*死鎖:兩個線程都在等待對方先完成,造成程序的停滯;

*產(chǎn)生死鎖的條件:

*兩個或兩個以上的線程在活動;

*某個線程拿到一個鎖以后,還想拿第二個鎖,造成鎖的嵌套?

*解決方法:

*當(dāng)前線程先釋放自己的鎖?

*盡量減少同步方法或同步代碼塊的嵌套?

Eg:兩個小孩互換玩具;

Eg:此示例不會產(chǎn)生死鎖;

/**

* 模擬死鎖

*/

public class Test {

public static void main(String[] args) {

Thread tang=new Thread(new Tang());

Thread dou=new Thread(new Dou());

tang.start();

dou.start();

}

}

/**

* 堂堂

*/

class Tang implements Runnable{

Object bobby=new Object();//芭比娃娃

Object duck=new Object();//玩具

@Override

public void run() {

synchronized (bobby) {

try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (duck) {

}

System.out.println("堂堂把芭比娃娃給豆豆玩!");

}

}

}

/**

* 豆豆

*/

class Dou implements Runnable{

Object bobby=new Object();//芭比娃娃

Object duck=new Object();//玩具

@Override

public void run() {

synchronized (duck) {

try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (bobby) {

}

System.out.println("豆豆把玩具鴨給堂堂玩");

}

}

}

Eg:此示例產(chǎn)生了死鎖

/**

* 模擬死鎖(產(chǎn)生了死鎖)

*/

public class Test1 {

public static void main(String[] args) {

Object bobby=new Object();

Object duck=new Object();

Thread tang=new Thread(new Tangtang(bobby,duck));

Thread dou=new Thread(new Doudou(bobby,duck));

tang.start();

dou.start();

}

}

/**

* 堂堂

*/

class Tangtang implements Runnable{

Object bobby;//芭比娃娃

Object duck;//玩具

//構(gòu)造函數(shù)

public Tangtang(Object bobby,Object duck) {

super();

this.bobby=bobby;

this.duck=duck;

}

@Override

public void run() {

synchronized (bobby) {

try {

Thread.sleep(500);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

synchronized (duck) {

}

System.out.println("堂堂把芭比娃娃給豆豆玩!");

}

}

}

/**

* 豆豆

*/

class Doudou implements Runnable{

Object bobby;//芭比娃娃

Object duck;//玩具

//構(gòu)造函數(shù)

public Doudou(Object bobby,Object duck) {

super();

this.bobby=bobby;

this.duck=duck;

}

@Override

public void run() {

synchronized (duck) {

try {

Thread.sleep(500);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

synchronized (bobby) {

}

System.out.println("豆豆把玩具鴨給堂堂玩");

}

}

}

14、附加2:生產(chǎn)者和消費者的問題: 生產(chǎn)者不斷生產(chǎn),消費者不斷取走生產(chǎn)者的產(chǎn)品;生產(chǎn)者生產(chǎn)出信息之后將其放到一個區(qū)域中,之后消費者從此區(qū)域取走數(shù)據(jù);

Eg:一個輪流錄入電影和讀取電影信息的程序

變形金剛——一部科幻電影

神偷奶爸——一部3D動畫片

分析: 生產(chǎn)者:錄入信息;

消費者:讀取信息;

/**

* 電影類

*/

public class Movie {

private String name;//電影的名稱

private String info;//電影的描述

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getInfo() {

return info;

}

public void setInfo(String info) {

this.info = info;

}

}

/**

* 生產(chǎn)者

*/

public class Producer implements Runnable {

private Movie movie=null;

private boolean flag=false;

//構(gòu)造函數(shù)

public Producer(Movie movie) {

super();

this.movie=movie;

}

@Override

public void run() {

//循環(huán)錄入50遍電影數(shù)據(jù),兩部電影交替錄入

for (int i = 0; i < 50; i++) {

if(flag) {

this.movie.setName("變形金剛");

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.movie.setInfo("一部科幻電影!");

flag=false;

}else {

this.movie.setName("神偷奶爸");

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.movie.setInfo("一部3D動畫電影");

flag=true;

}

}

}

}

/**

* 測試類

*/

public class Test {

public static void main(String[] args) {

Movie movie=new Movie();

//生產(chǎn)者線程對象

Thread producer=new Thread(new Producer(movie));

//消費者線程對象

Thread consumer=new Thread(new Consumer(movie)); ?? producer.start();

consumer.start();

}

}

/**

* 消費者

*/

public class Consumer implements Runnable {

private Movie movie=null;

//構(gòu)造函數(shù)

public Consumer(Movie movie) {

super();

this.movie=movie;

}

@Override

public void run() {

//循環(huán)顯示50次電影信息

for (int i = 0; i <50; i++) {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(this.movie.getName()+"—

"+this.movie.getInfo());

}

}

}

輸出結(jié)果:(會出現(xiàn)電影名與類型匹配錯誤的情況(生產(chǎn)與消費不同步))

/**

* 生產(chǎn)者

*/

public class Producer implements Runnable {

private Movie movie=null;

private boolean flag=false;

//構(gòu)造函數(shù)

public Producer(Movie movie) {

super();

this.movie=movie;

}

@Override

public void run() {

//循環(huán)錄入50遍電影數(shù)據(jù),兩部電影交替錄入

for (int i = 0; i < 50; i++) {

if(flag) {

this.movie.set("變形金剛", "一部科幻電影");

flag=false;

}else {

this.movie.set("神偷奶爸", "一部3D動畫電影");

flag=true;

}

}

}

}

/**

* 消費者

*/

public class Consumer implements Runnable {

private Movie movie=null;

//構(gòu)造函數(shù)

public Consumer(Movie movie) {

super();

this.movie=movie;

}

@Override

public void run() {

//循環(huán)顯示50次電影信息

for (int i = 0; i <50; i++) {

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.movie.get();

}

}

}

package lianxi0Producer;

/**

* 電影類

*/

public class Movie {

private String name;//電影的名稱

private String info;//電影的描述

public String getName() {

return name;

}

public String getInfo() {

return info;

}

//同步寫入

public synchronized void set(String name,String info) {

this.name=name;

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.info=info;

}

//同步獲取

public synchronized void get() {

System.out.println(this.getName()+"--"+this.getInfo());

}

}

/**

* 測試類

*/

public class Test {

public static void main(String[] args) {

Movie movie=new Movie();

//生產(chǎn)者線程對象

Thread producer=new Thread(new Producer(movie));

//消費者線程對象

Thread consumer=new Thread(new Consumer(movie));? ?? producer.start();

consumer.start();

}

}

輸出結(jié)果:(沒有實現(xiàn)交替輸出(需要調(diào)用Object類的兩個方法))

notify()喚醒正在等待對象監(jiān)視器的單個線程。

Wait():導(dǎo)致當(dāng)前線程等待,直到另一個線程調(diào)用該對象的 notify()方法或 notifyAll()方法。

/**

* 生產(chǎn)者

*/

public class Producer implements Runnable {

private Movie movie=null;

private boolean flag=false;

//構(gòu)造函數(shù)

public Producer(Movie movie) {

super();

this.movie=movie;

}

@Override

public void run() {

//循環(huán)錄入50遍電影數(shù)據(jù),兩部電影交替錄入

for (int i = 0; i < 50; i++) {

if(flag) {

this.movie.set("變形金剛", "一部科幻電影");

flag=false;

}else {

this.movie.set("神偷奶爸", "一部3D動畫電影");

flag=true;

}

}

}

}

/**

* 消費者

*/

public class Consumer implements Runnable {

private Movie movie=null;

//構(gòu)造函數(shù)

public Consumer(Movie movie) {

super();

this.movie=movie;

}

@Override

public void run() {

//循環(huán)顯示50次電影信息

for (int i = 0; i <50; i++) {

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.movie.get();

}

}

}

/**

* 電影類

*/

public class Movie {

private String name;//電影的名稱

private String info;//電影的描述

private boolean flag=true;//設(shè)置標(biāo)志位置,控制生產(chǎn)者生產(chǎn),消費者消費

public String getName() {

return name;

}

public String getInfo() {

return info;

}

//同步寫入

public synchronized void set(String name,String info) {

if(!flag) {

try {

super.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

this.name=name;

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.info=info;

flag=false;//重置標(biāo)志位,讓消費者消費

super.notify();

}

//同步獲取

public synchronized void get() {

if(flag) {

try {

super.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

System.out.println(this.getName()+"—

"+this.getInfo());

flag=true;

super.notify();

}

}

/**

* 測試類

*/

public class Test {

public static void main(String[] args) {

Movie movie=new Movie();

//生產(chǎn)者線程對象

Thread producer=new Thread(new Producer(movie));

//消費者線程對象

Thread consumer=new Thread(new Consumer(movie));???? producer.start();

consumer.start();

}

}

輸出結(jié)果:

15、附加:線程池:

●使用線程池的理由:

◆線程缺乏統(tǒng)一管理,占用過多的系統(tǒng)資源;

◆缺乏更多的功能,如:定期執(zhí)行、定時執(zhí)行等;

●線程池的優(yōu)點:

◆重用存在的線程、減少對象的創(chuàng)建、消亡的開銷;

◆有效控制最大并發(fā)數(shù),提高系統(tǒng)資源使用率;

◆定時執(zhí)行、定期執(zhí)行;

●線程池所在的包:java.util.concurrent;? ?:頂級接口是Executor,真正的線程池接口是ExecutorService;

Java.util.concurrent.Executors類提供創(chuàng)建線程池的方法;

方法名

說明

newCachedThreadPool()

創(chuàng)建一個可緩存的線程池,有任務(wù)時才創(chuàng)建新任務(wù);

newSingleThreadExecutor()

創(chuàng)建一個單線程池

newFixedThreadPool(int nThreads)

創(chuàng)建一個固定長度的線程池,空閑線程池會一直保留,參數(shù)nThreads設(shè)定線程池中線程的數(shù)目

newScheaduledThreadPool(int corePoolSize)

創(chuàng)建了一個固定長度的線程池,而且以延遲或定時的方式來執(zhí)行任務(wù);

●使用newCacherThreadPool()方法創(chuàng)建線程池1:

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

/**

* 使用newCacherThreadPool()方法創(chuàng)建線程池

* @author 逆風(fēng)?飛翔

*

*/

public class Test {

public static void main(String[] args) {

//創(chuàng)建一個線程池

ExecutorService cachedThreadPool= Executors.newCachedThreadPool();

//在線程池中執(zhí)行10個任務(wù)

for (int i = 0; i < 10; i++) {

cachedThreadPool.execute(new MyRunnable(i));

try {

Thread.sleep(1000); //每執(zhí)行一次休眠一秒

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

class MyRunnable implements Runnable{

int num;

public MyRunnable(int num) {

super();

this.num=num;

}

@Override

public void run() {

System.out.println(Thread.currentThread().getName()+":"+num);

}

}

輸出結(jié)果:pool代表線程池

(10個任務(wù)被同一個線程執(zhí)行)

●使用newCacherThreadPool()方法創(chuàng)建線程池2:

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

/**

* 使用newCacherThreadPool()方法創(chuàng)建線程池

* @author 逆風(fēng)?飛翔

*

*/

public class Test {

public static void main(String[] args) {

//創(chuàng)建一個線程池

ExecutorService cachedThreadPool= Executors.newCachedThreadPool();?? //在線程池中執(zhí)行10個任務(wù)

for (int i = 0; i < 10; i++) {

cachedThreadPool.execute(new MyRunnable(i));

//????? try {

//???????? Thread.sleep(1000);

//????? } catch (InterruptedException e) {

//???????? e.printStackTrace();

//????? }

}

}

}

class MyRunnable implements Runnable{

int num;

public MyRunnable(int num) {

super();

this.num=num;

}

@Override

public void run() {

System.out.println(Thread.currentThread().getName()+":"+num);

}

}

結(jié)果:(更多的線程參與執(zhí)行,有些線程執(zhí)行了兩次,

eg:線程8執(zhí)行完7后,又繼續(xù)執(zhí)行了9,

省去創(chuàng)建一個新的線程,當(dāng)有一個線程閑置下來后不需要去銷毀,又去執(zhí)行了一個新的任務(wù))

●使用newSingleThreadExecutor()方法創(chuàng)建單線程池

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

/**

* 使用newSingleThreadExecutor()方法創(chuàng)建單線程池

*/

public class Test1 {

public static void main(String[] args) {

//創(chuàng)建一個單線程池

ExecutorService singleThreadPool= Executors.newSingleThreadExecutor();

//在線程池中執(zhí)行10個任務(wù)

for (int i = 0; i < 10; i++) {

singleThreadPool.execute(new MyRunnable(i));

//????? try {

//???????? Thread.sleep(1000);

//????? } catch (InterruptedException e) {

//???????? e.printStackTrace();

//????? }

}

}

}

class MyRunnable implements Runnable{

int num;

public MyRunnable(int num) {

super();

this.num=num;

}

@Override

public void run() {

System.out.println(Thread.currentThread().getName()+":"+num);

}

}

輸出結(jié)果:

●使用newFixedThreadExecutor()方法創(chuàng)建指定個數(shù)線程池

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

/**

* 使用newFixedThreadExecutor()方法創(chuàng)建單線程池

*/

public class Test2 {

public static void main(String[] args) {

//創(chuàng)建一個線程池

ExecutorService fixedThreadPool= Executors.newFixedThreadPool(3);

//在線程池中執(zhí)行10個任務(wù)

for (int i = 0; i < 10; i++) {

fixedThreadPool.execute(new McRunnable(i));

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

class McRunnable implements Runnable{

int num;

public McRunnable(int num) {

super();

this.num=num;

}

@Override

public void run() {

System.out.println(Thread.currentThread().getName()+":"+num);

}

}

輸出結(jié)果:(只有三個線程在執(zhí)行)

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

/**

* 使用newSchediledThreadPool()方法來創(chuàng)建線程池

*/

public class Test3 {

public static void main(String[] args) {

//創(chuàng)建三個線程

ScheduledExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(3);

System.out.println("*************開始執(zhí)行*************");

scheduledThreadPool.scheduleAtFixedRate(new MdRunnable(), 5, 2, TimeUnit.SECONDS);

}

}

class MdRunnable implements Runnable{

@Override

public void run() {

System.out.println(Thread.currentThread().getName()+"延時5s執(zhí)行,每2s執(zhí)行一次");

}

}

●ThreadPoolExecutor類

◆構(gòu)造器中各個參數(shù)的含義:

★corePoolSize:核心池的大小;

★maximumPoolSize:線程池最大線程數(shù);

★keepAliveTime:表示線程沒有任務(wù)執(zhí)行時最多保持多久時間會終止;

★unit:參數(shù)keepAliveTime的時間單位;

★workQueue:一個阻塞隊列,用來存儲等待執(zhí)行的任務(wù);

★threadFactory:線程工廠,主要用來創(chuàng)建線程;

★handler:表示當(dāng)拒絕處理任務(wù)時的策略;

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

/**

* 創(chuàng)建自定義線程池

*/

public class Test4 {

public static void main(String[] args) {

//創(chuàng)建一個自定義線程池(核心線程數(shù),最大線程數(shù),超出的線程消亡的時間,指定毫秒數(shù),阻塞隊列)

ThreadPoolExecutor executor=new ThreadPoolExecutor(5, 7, 3000,

TimeUnit.MICROSECONDS, new ArrayBlockingQueue(4));

//執(zhí)行12個任務(wù)

for (int i = 1; i <=12; i++) {

//i為傳入當(dāng)前執(zhí)行的數(shù)量

executor.execute(new MmRunnable(i));

System.out.println("線程池中的線程數(shù):"+executor.getPoolSize()+

",隊列中等待執(zhí)行的任務(wù):"+executor.getQueue().size()+

",已執(zhí)行完成的任務(wù)數(shù):"+executor.getCompletedTaskCount());

}

executor.shutdown();//關(guān)閉線程池

}

}

class MmRunnable implements Runnable{

int num;//第幾個任務(wù)

public MmRunnable(int num) {

super();

this.num=num;

}

@Override

public void run() {

System.out.println("正在執(zhí)行任務(wù)"+num);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("任務(wù)"+num+"執(zhí)行完畢!");

}

}

運行結(jié)果:

(會創(chuàng)建第12個線程所以會報錯)

16、附加:

●進程和線程的基本概念和原理:

一個進程至少包含一個線程,即主線程。

多個線程的執(zhí)行時間是由CPU的時間片決定的,時長是隨機的。

在單CPU計算機中,一個進程的多個線程是交替執(zhí)行的,在某一時刻,只能執(zhí)行一個線程。

●線程是進程的一個執(zhí)行路徑,而不是一個程序,

線程是進程中執(zhí)行運算的最小單位,

多線程用于實現(xiàn)并發(fā),

單CPU的計算機中,CPU每個時刻只能執(zhí)行一條指令,將CPU的執(zhí)行時間分成多個時間片,分配給不同的線程。

●線程的創(chuàng)建和啟動。當(dāng)線程被創(chuàng)建后,執(zhí)行start()方法后,線程處于可運行狀態(tài)。

當(dāng)線程執(zhí)行完一個時間片后繼續(xù)回到就緒狀態(tài),等待CPU再次分配時間片,而不存在一個隊列。

線程休眠后,處于阻塞狀態(tài)。

●線程的創(chuàng)建和啟動,線程類的定義有繼承Thead類和實現(xiàn)Runable接口兩種方式,

通過實現(xiàn)run()方法編寫線程體,

已啟動的線程不能重復(fù)調(diào)用start()方法,否則會報IllegalThreadStateException異常。

●當(dāng)線程對象調(diào)用start()方法后,進入就緒狀態(tài),

當(dāng)CPU分配時間片后即可執(zhí)行,可以實現(xiàn)多線程并發(fā),

而直接調(diào)用run()方法和調(diào)用普通方法一樣,只有主線程一條執(zhí)行路徑,不能實現(xiàn)并發(fā)執(zhí)行。

●eg:

分析:

本題考察線程的狀態(tài)。創(chuàng)建一個線程對象后,線程對象處于新建狀態(tài),執(zhí)行start()方法后,處于就緒狀態(tài)。休眠時處于阻塞狀態(tài),休眠后處于就緒狀態(tài),執(zhí)行輸出語句時處于執(zhí)行狀態(tài)。

Eg:

分析:

本題主要考查線程的強制執(zhí)行。當(dāng)主線程 main方法執(zhí)行System.out.println(a);這條語句時,線程還沒有真正開始運行,或許正在為它分配資源準(zhǔn)備運行。因為為線程分配資源需要時間,而main方法執(zhí)行完t.start()方法后繼續(xù)往下執(zhí)行System.out.println(a);,這個時候得到的結(jié)果是a還沒有被改變的值0 。怎樣才能讓輸出結(jié)果為5, join() 方法提供了這種功能。它能夠使調(diào)用該方法的線程在此之前執(zhí)行完畢。

●eg:

分析:本題考察線程的創(chuàng)建。在自定義線程中如果沒有重寫run()方法,則默認(rèn)執(zhí)行父類Thread中的run()方法,因此不會出現(xiàn)編譯錯誤,也無任務(wù)輸出結(jié)果,

●Eg:

分析:本題考察如何獲取當(dāng)前線程。線程對象mt直接調(diào)用了run()方法,沒有使用start()方法啟動線程。因此本題目中只啟動了主線程和new Thread(mt,"線程"),主線程的線程名為main.

Eg:

分析:sleep()方法,它不能終止一個線程,它是將線程睡眠一段時間。當(dāng)時間結(jié)束以后,線程就會再次啟動。它是不會交出線程鎖的

Eg:

分析:

因為currentThread()是靜態(tài)方法,使用類名可直接調(diào)用。

Eg:

分析:

本題考察線程安全的類型。當(dāng)多個線程共同操作Counter類的成員變量count時,會引出線程安全問題。解決問題的辦法就是對addCount()方法加鎖。如果將count變量定義在addCount()方法中,就不會存在多線程共同操作的數(shù)據(jù),不會引發(fā)并發(fā)問題,本題答案為bc

Eg;

D:一個類中可以有多個同步方法或同步代碼塊;

●synchronized用來定義同步方法或同步代碼塊,解決多個線程共享資源時帶來的問題,同步后,只允許一個線程進入同步方法或同步代碼塊。

對于synchronized關(guān)鍵字最精準(zhǔn)的描述:保證在某個時刻只有一個線程可以訪問方法或?qū)ο?#xff1b;

●synchronized是Java中的關(guān)鍵字,是一種同步鎖。它修飾的對象有以下幾種:

1.修飾一個代碼塊,被修飾的代碼塊稱為同步語句塊,其作用的范圍是大括號{}括起來的代碼,作用的對象是調(diào)用這個代碼塊的對象;

2.修飾一個方法,被修飾的方法稱為同步方法,其作用的范圍是整個方法,作用的對象是調(diào)用這個方法的對象;

3.修改一個靜態(tài)的方法,其作用的范圍是整個靜態(tài)方法,作用的對象是這個類的所有對象;

4.修改一個類,其作用的范圍是synchronized后面括號括起來的部分,作用主的對象是這個類的所有對象。

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com

特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點,本站所提供的攝影照片,插畫,設(shè)計作品,如需使用,請與原作者聯(lián)系,版權(quán)歸原作者所有

總結(jié)

以上是生活随笔為你收集整理的java获取其他类的线程,使用Java实现面向对象编程——第七章 多线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。