真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

關(guān)于Java的并發(fā)編程

關(guān)于JAVA并發(fā)編程的那些事。

成都創(chuàng)新互聯(lián)公司專(zhuān)注于溪湖網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供溪湖營(yíng)銷(xiāo)型網(wǎng)站建設(shè),溪湖網(wǎng)站制作、溪湖網(wǎng)頁(yè)設(shè)計(jì)、溪湖網(wǎng)站官網(wǎng)定制、小程序制作服務(wù),打造溪湖網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供溪湖網(wǎng)站排名全網(wǎng)營(yíng)銷(xiāo)落地服務(wù)。

記錄一下自己在學(xué)習(xí)并發(fā)編程的時(shí)候遇到的一些問(wèn)題。方便自己查閱。

1.實(shí)現(xiàn)Runnable接口好在哪里?

從代碼架構(gòu)角度:具體的任務(wù)(run方法)應(yīng)該和“創(chuàng)建和運(yùn)行線(xiàn)程的機(jī)制”(Thread類(lèi))相解耦。

使用繼承Thread類(lèi)的方式的話(huà),那么每次想新建一個(gè)任務(wù),只能新建一個(gè)獨(dú)立的線(xiàn)程們這樣做的話(huà)損耗會(huì)比較大(比如重新創(chuàng)建一個(gè)線(xiàn)程,執(zhí)行完畢

以后再銷(xiāo)毀等。如果實(shí)際工作內(nèi)容,也就是run()函數(shù)里只是簡(jiǎn)單的打印一行文字的話(huà),那么可能線(xiàn)程的實(shí)際工作內(nèi)容還不如損耗來(lái)的大)。如果使用Runnable和線(xiàn)程池,就可以大大減少這樣的損耗。

繼承Thread類(lèi)以后,由于Java語(yǔ)音不支持多繼承,這樣就無(wú)法再繼承其他的類(lèi),限制了可擴(kuò)展性。

2.“實(shí)現(xiàn)Runnable接口并傳入Thread類(lèi)”和繼承Thread類(lèi),然后重寫(xiě)run()方法的本質(zhì)對(duì)比?

在實(shí)現(xiàn)多線(xiàn)程的本質(zhì)上,并沒(méi)有區(qū)別,都是最終調(diào)用了start()方法來(lái)新建線(xiàn)程。這兩個(gè)方法最主要的區(qū)別是在于run()的了內(nèi)容來(lái)源。

//以下代碼在Thread類(lèi)中,可以找到

@override

public void run(){

if(target!=null){

target.run();

}

}

實(shí)現(xiàn)Runnable接口最終調(diào)用target.run()。繼承Thread類(lèi),是整個(gè)run()方法都被重寫(xiě)。

3.有幾種創(chuàng)建線(xiàn)程的方法?

從不同的角度看,會(huì)有不同的答案。

典型答案是兩種,分別是實(shí)現(xiàn)Runnable接口和繼承Thread類(lèi)

但是我們看原理,其實(shí)Thread類(lèi)實(shí)現(xiàn)了Runnable接口,并且Thread類(lèi)的run()方法,會(huì)發(fā)現(xiàn)其實(shí)哪兩種本質(zhì)是一樣的。兩種方式在實(shí)現(xiàn)多線(xiàn)程的本質(zhì)上,并沒(méi)有區(qū)別。

還有其他實(shí)現(xiàn)線(xiàn)程的方法,例如線(xiàn)程池等,他們也能新建線(xiàn)程,但是細(xì)看源碼,并沒(méi)有逃過(guò)本質(zhì),也是實(shí)現(xiàn)Runnable接口和繼承Thread類(lèi)。

結(jié)論:我們只能那個(gè)通過(guò)新建Thread類(lèi)這一種方式來(lái)出創(chuàng)建線(xiàn)程,但是類(lèi)里面的run方法有兩種方式實(shí)現(xiàn),的一種是重寫(xiě)run()方法,第二種是實(shí)現(xiàn)Runnable接口的run方法,然后再把該Runnable實(shí)例傳給Thread類(lèi)。除此之外,從表面上看線(xiàn)程池、定時(shí)器等工具類(lèi)也能創(chuàng)建線(xiàn)程,但是他們的本質(zhì)也是逃不過(guò)剛說(shuō)的范圍。

4.start方法的執(zhí)行流程是什么?

檢查線(xiàn)程狀態(tài),只有New狀態(tài)的線(xiàn)程才能繼續(xù),否則會(huì)拋出IllegalThreadStateException。運(yùn)行或已經(jīng)結(jié)束的線(xiàn)程都不能再啟動(dòng)。

(這里可引申面試題:一個(gè)線(xiàn)程調(diào)用兩次start()方法會(huì)出現(xiàn)什么情況?why?解題思路就是1異常2線(xiàn)程狀態(tài))

被加入線(xiàn)程組

調(diào)用start0()方法啟動(dòng)線(xiàn)程。

Tips:start方法是被synchronized修飾的方法,可以保證線(xiàn)程安全。并且由JVM產(chǎn)檢的main方法和system組線(xiàn)程,并不會(huì)通過(guò)start來(lái)啟動(dòng)。

5.Java中如何正確停止線(xiàn)程?

用interrupt來(lái)請(qǐng)求停止線(xiàn)程。(僅僅是通知到被終止的線(xiàn)程應(yīng)該停止運(yùn)行了,被停止的線(xiàn)程自身?yè)碛袥Q定權(quán)。這是一個(gè)協(xié)作機(jī)制。)

想要停止線(xiàn)程,需要請(qǐng)求方,被停止方,子方法被調(diào)用方相互配合才行:

– a.作為被停止方:每次循環(huán)或者適時(shí)檢測(cè)中斷信號(hào),并且在可能拋出interruptedException的地方處理該中斷信號(hào);

– b.請(qǐng)求方:發(fā)出中斷信號(hào)。

– c.子方法調(diào)用方:要注意優(yōu)先在方法拋出InterruptedException,或者在檢查到中斷信號(hào)時(shí),再次設(shè)置中斷狀態(tài)。(Catch里會(huì)重置這個(gè)狀態(tài),需要再次設(shè)置中斷狀態(tài),否則就被吞了)

最后,錯(cuò)誤的方法: stop、suspend方法已經(jīng)被廢棄(stop容易造成臟數(shù)據(jù))

volatile的boolean標(biāo)記,無(wú)法處理長(zhǎng)時(shí)間阻塞的情況(例如,生產(chǎn)者消費(fèi)者模式中,就存在這樣的情況,生產(chǎn)者生產(chǎn)速度快,消費(fèi)者消費(fèi)速度慢,生產(chǎn)者隊(duì)列阻塞)

6.無(wú)法響應(yīng)中斷時(shí)如何停止線(xiàn)程?

如果線(xiàn)程阻塞是由于調(diào)用了wait()、sleep()或者join()方法,你可以中斷線(xiàn)程,通過(guò)拋出interruptedException異常來(lái)喚醒該線(xiàn)程,但是對(duì)于不能響應(yīng)InterruptedException的阻塞,并沒(méi)有一個(gè)通用的解決方案。但是我們可以利用特定的其他可以響應(yīng)中斷的方法,比如Reentrantlock.lockInterruptibly(),比如關(guān)閉套接字使線(xiàn)程立即返回等方法來(lái)達(dá)到目的。答案有很多種,因?yàn)橛泻芏嘣驎?huì)造成線(xiàn)程阻塞,所以針對(duì)不同的情況,喚起的方法不同??偨Y(jié)來(lái)說(shuō),如果不支持響應(yīng)中斷,就要用特定的方法來(lái)喚起。根據(jù)不同的類(lèi),調(diào)用不同的方法。

.可以響應(yīng)中斷而拋出InterruptedException的常見(jiàn)方法?

Object.wait()/wait(long)/wait(long,int)

Thread.sleep()/sleep(long,int)

Thread.join()/join(long)/join(long,int)

java.util.concurrent.BlockingQueue.take()/put(E)

java.util.concurrent.locks.Lock.lockInterruptibly()

java.util.concurrent.countDownLatch.await()

java.util.concurrent.cyclicBarrier.await()

java.uti.concurrent.Exchanger.exchange(V)

java.nio.channels.InterruptibleChannel相關(guān)方法

java.nio.channels.Selector相關(guān)方法

7.判斷線(xiàn)程是否被中斷的方法有哪些?

static boolean interrupted() //返回之后,清除標(biāo)記

boolean isInterrupted() //不清除

//Tip:注意Thread.intterupted()的目的對(duì)象時(shí)“當(dāng)前線(xiàn)程”,而不管本方法來(lái)自于哪個(gè)對(duì)象

8.線(xiàn)程都有哪幾個(gè)狀態(tài)?

6種狀態(tài)

New:已經(jīng)創(chuàng)建,但是還沒(méi)有執(zhí)行start方法

Runnable:一旦調(diào)用了start方法后,就一定會(huì)到Runnable,java中的Runnable對(duì)應(yīng)操作系統(tǒng)里的ready和running狀態(tài)

Blocked:當(dāng)一個(gè)線(xiàn)程進(jìn)入同步代碼塊(被Synchronized修飾),該鎖被其他線(xiàn)程拿走了。線(xiàn)程變成Blocked。只有Synchronized才能rag線(xiàn)程進(jìn)入這個(gè)狀態(tài)。

Wating:等待

Time_waiting:計(jì)時(shí)等待

Terminated:死亡

9.線(xiàn)程相關(guān)方法

Thread類(lèi):

sleep相關(guān)、

join() :等待其他線(xiàn)程執(zhí)行完畢

yield相關(guān) :放棄已經(jīng)獲得的CPU資源

currentThread:獲取當(dāng)前線(xiàn)程的引用

start,run方法:?jiǎn)?dòng)線(xiàn)程相關(guān)

interrupt相關(guān)::中斷線(xiàn)程

stop() suspend() resuem()相關(guān) :已經(jīng)廢棄

Object類(lèi):

wait():讓線(xiàn)程短暫休息

notify/notifyAll 相關(guān) :?jiǎn)拘丫€(xiàn)程

10.wait/notify/notifyAll的作用和用法?

階段  方法和作用

阻塞階段  調(diào)用wait()方法

喚醒階段  1、另一個(gè)線(xiàn)程調(diào)用這個(gè)對(duì)象的notify方法且剛好被喚醒的是本線(xiàn)程。2、另外一個(gè)線(xiàn)程調(diào)用這個(gè)對(duì)象的notifyAll方法。3、過(guò)了wait(long timeOut)的規(guī)定的超時(shí)時(shí)間,如果傳入0就是永久等待。4、線(xiàn)程自身調(diào)用了intterrupt()

遇到中斷  wait階段遇到中斷會(huì)拋出異常,并且釋放掉鎖

11.wait、notify、notifyAll特點(diǎn)?性質(zhì)?

用必須先擁有monitor鎖。(Synchronized)

notify只能喚醒一個(gè)線(xiàn)程。

屬于Object類(lèi),是所有對(duì)象的父類(lèi),所以任何對(duì)象都能調(diào)用,并且都是native final的。

類(lèi)似Condition的功能

同時(shí)持有多個(gè)鎖的情況。釋放鎖,只能釋放現(xiàn)在wait所對(duì)應(yīng)的對(duì)象的那把鎖。

12.用wait/notify方法實(shí)現(xiàn)消費(fèi)者生產(chǎn)者模式?

package com.yue.consumer;

import java.util.Date;

import java.util.LinkedList;

//使用wait notify實(shí)現(xiàn)一個(gè)生產(chǎn)者消費(fèi)者模式

public class ProducerConsumerModel {

public static void main(String[] args) {

EventStorage storage = new EventStorage();

Producer producer = new Producer(storage);

Consumer consumer =new Consumer(storage);

new Thread(producer).start();

new Thread(consumer).start();

}

}

class Producer implements Runnable{

private EventStorage storage;

public Producer(EventStorage storage) {

this.storage = storage;

}

public void run() {

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

storage.put();

}

}

}

class Consumer implements Runnable{

private EventStorage storage;

public Consumer(EventStorage storage) {

this.storage = storage;

}

public void run() {

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

storage.take();

}

}

}

class EventStorage{

private int maxSize;

private LinkedList storage;

public EventStorage() {

this.maxSize = 10;

this.storage = new LinkedList();

}

public synchronized void put(){

while(storage.size() == maxSize){

try {

wait();

}catch (InterruptedException e){

e.printStackTrace();

}

}

storage.add(new Date());

System.out.println("倉(cāng)庫(kù)里有了"+storage.size()+"個(gè)產(chǎn)品");

notify();

}

public synchronized void take(){

while(storage.size()==0){

try {

wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}鄭州婦科在線(xiàn)醫(yī)生 http://www.zzkdfk120.com/

System.out.println("拿到了"+storage.poll()+",現(xiàn)在倉(cāng)庫(kù)還剩下"+storage.size());

notify();

}

}

13.為什么wait需要在同步代碼塊中使用,而sleep不需要?

為了讓線(xiàn)程之間的通信更加可靠,防止死鎖或者永久等待。如果不放在synchronized中的話(huà),那么久有可能在線(xiàn)程執(zhí)行到一個(gè)wait之前,切換到另外一個(gè)線(xiàn)程。而另外一個(gè)線(xiàn)程執(zhí)行完notify后,切換回來(lái)。這樣就沒(méi)有線(xiàn)程去喚醒它了。而sleep是針對(duì)自己線(xiàn)程的,和其他線(xiàn)程的關(guān)系不大。

14.為什么wait、notify和notifyAll定義在object類(lèi)中,sleep定義在Thread類(lèi)中?

因?yàn)樵贘ava中,這三個(gè)操作都是所級(jí)別的操作,而鎖是針對(duì)對(duì)象的。鎖是綁定到對(duì)象中,而不是綁定到線(xiàn)程。

15.wait是屬于Object對(duì)象的,那調(diào)用Thread.wait()會(huì)出現(xiàn)什么情況?

會(huì)導(dǎo)致流程問(wèn)題。因?yàn)樵诰€(xiàn)程退出的時(shí)候,會(huì)自動(dòng)執(zhí)行一個(gè)notify

16.sleep方法的作用?

作用:讓線(xiàn)程在預(yù)期執(zhí)行,其他時(shí)候不占用CPU資源

特點(diǎn):Sleep方法可以讓線(xiàn)程進(jìn)入waiting狀態(tài),并且不占用CPU資源,但是不釋放鎖(包含synchronized和lock),直到規(guī)定時(shí)間之后在執(zhí)行。休眠期內(nèi)如果被中斷,會(huì)拋出異常并清除中斷狀態(tài)。

Tips:

//這兩種方式其實(shí)都是一樣的,但是第一種比較優(yōu)雅

TimeUnit.SECONDS.sleep()

Thread.sleep()

17.wait和sleep方法的異同?

相同:

Wait和sleep方法都可以使線(xiàn)程阻塞,對(duì)應(yīng)線(xiàn)程狀態(tài)是Waiting或Time_Waiting。

wait和sleep方法都可以響應(yīng)中斷Thread.interrupt()。

不同點(diǎn):

wait方法的執(zhí)行必須在同步方法中進(jìn)行,而sleep則不需要。

在同步方法里執(zhí)行sleep方法時(shí),不會(huì)釋放monitor鎖,但是wait方法會(huì)釋放monitor鎖。

sleep方法短暫休眠之后會(huì)主動(dòng)退出阻塞,而沒(méi)有指定時(shí)間的 wait方法則需要被其他線(xiàn)程中斷后才能退出阻塞。

wait()和notify(),notifyAll()是Object類(lèi)的方法,sleep()和yield()是Thread類(lèi)的方法

TIps:Java設(shè)計(jì)的時(shí)候把對(duì)象都當(dāng)成一把鎖,對(duì)象頭中都有鎖的狀態(tài)

18. join()方法的作用?

作用:因?yàn)樾戮€(xiàn)程加入我們,所以得等他執(zhí)行完再出發(fā);通常是,主線(xiàn)程等待子線(xiàn)程,而不是子線(xiàn)程等待主線(xiàn)程。例如一般是main等thread1執(zhí)行完。join遇到中斷時(shí)候是主線(xiàn)程被中斷,是主線(xiàn)程拋出異常;在join期間狀態(tài)是waiting

Tips:CountDownLatch或CyclicBarrier類(lèi)封裝了join。建議使用封裝好的工具

源碼:

調(diào)用了thread.wait方法,而這方法會(huì)在thread執(zhí)行結(jié)束后悔自動(dòng)調(diào)用notify。這也是為什么不要使用這個(gè)的原因。

19.yield()方法的作用?

作用:釋放cpu時(shí)間片,線(xiàn)程狀態(tài)是runnable,而不是bolcked,也不是waiting。常用于并發(fā)包中。

yield 和 sleep:

sleep期間屬于被阻塞,yield不是阻塞,隨時(shí)是runable狀態(tài)。而且JVM是不保證遵循的。

20.線(xiàn)程都有哪些屬性?

編號(hào)(ID):每個(gè)編程都有自己的ID,用于標(biāo)識(shí)不同的線(xiàn)程。

名稱(chēng)(Name):作用是讓用戶(hù)或者程序員在開(kāi)發(fā)、調(diào)試或運(yùn)行過(guò)程中,更容易區(qū)分每個(gè)不同的線(xiàn)程,定位問(wèn)題等。

是否是守護(hù)線(xiàn)程(isDeamon) :true代表該線(xiàn)程是守護(hù)線(xiàn)程,false代表線(xiàn)程是非守護(hù)線(xiàn)程,也就是用戶(hù)線(xiàn)程。

– 作用:給用戶(hù)線(xiàn)程提供服務(wù)。例如垃圾處理器。

– 特性:線(xiàn)程類(lèi)型默認(rèn)繼承自父線(xiàn)程。被誰(shuí)啟動(dòng),一般都是JVM啟動(dòng)的,(main)。不影響JVM退出。

– 區(qū)別:整體無(wú)區(qū)別。唯一區(qū)別在于是否影響JVM退出。

優(yōu)先級(jí)(Priority):優(yōu)先級(jí)這個(gè)屬性的目的是告訴線(xiàn)程調(diào)度器,用戶(hù)希望哪些線(xiàn)程相對(duì)多運(yùn)行,哪些少運(yùn)行。

– 10個(gè)優(yōu)先級(jí),默認(rèn)5.

– 程序的設(shè)計(jì)不應(yīng)該優(yōu)先級(jí)

21.實(shí)際工作中,如何全局處理異常?為什么要全局處理?不處理行不行?

主線(xiàn)程可以啟動(dòng)發(fā)現(xiàn)異常,子線(xiàn)程卻不行。比如主線(xiàn)程操作非常多,子線(xiàn)程雖然報(bào)異常,但是日志太多,不好發(fā)覺(jué)。并且在子線(xiàn)程發(fā)現(xiàn)問(wèn)題后,并沒(méi)有停止執(zhí)行。

子線(xiàn)程異常無(wú)法用傳統(tǒng)方法捕獲。

不能直接捕獲的后果,可能線(xiàn)程掛掉打印堆棧。用了全局處理之后提高健壯性,可以在發(fā)生未知異常后,重啟線(xiàn)程或者通知程序員等。

22.關(guān)于線(xiàn)程異常的兩種處理方法?

方案一:手動(dòng)在每個(gè)run()方法里進(jìn)行try catch (不推薦)

方案二:利用UncaughtExceptionHanler接口

– void uncaughtException (Thread t,Throwable e)

– 異常處理器的調(diào)用策略:首先會(huì)檢查父線(xiàn)程,一直往上找,查找是否有人能夠處理。

– 實(shí)現(xiàn):

首先,自定義一個(gè)類(lèi)實(shí)現(xiàn)Thread.UncaughtExceptionHandler。重寫(xiě)內(nèi)置方法uncaughtException(Thread t,Throwable e)方法,里面寫(xiě)自己的邏輯。(Tips:可以通過(guò)構(gòu)造方法來(lái)傳模塊名字)

然后,在需要配置的類(lèi)中setDefaultUncaughtExceptionHandler(new HandlerInstance);


文章標(biāo)題:關(guān)于Java的并發(fā)編程
URL分享:http://weahome.cn/article/pepgdj.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部