国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
java中的并發(fā)及其安全性

java中的并發(fā)及其安全性

                                      

所有重要的操作系統(tǒng)都支持進(jìn)程的概念 —— 獨(dú)立運(yùn)行的程序,在某種程度上相互隔離。

線程有時(shí)稱為 輕量級(jí)進(jìn)程。與進(jìn)程一樣,它們擁有通過程序運(yùn)行的獨(dú)立的并發(fā)路徑,

并且每個(gè)線程都有自己的程序計(jì)數(shù)器,稱為堆棧和本地變量。然而,線程存在于進(jìn)程中,

它們與同一進(jìn)程內(nèi)的其他線程共享內(nèi)存、文件句柄以及每進(jìn)程狀態(tài)。

在 Java 程序中存在很多理由使用線程,并且不管開發(fā)人員知道線程與否,幾乎每個(gè)

Java 應(yīng)用程序都使用線程。許多 J2SE 和 J2EE 工具可以創(chuàng)建線程,如 RMI、Servlet、Enterprise JavaBeans

 組件和 Swing GUI 工具包。

AWT 和 Swing
這些 GUI 工具包創(chuàng)建了稱為時(shí)間線程的后臺(tái)線程,將從該線程調(diào)用通過 GUI 組件注冊(cè)的

監(jiān)聽器。因此,實(shí)現(xiàn)這些監(jiān)聽器的類必須是線程安全的。

TimerTask
JDK 1.3 中引入的 TimerTask 工具允許稍后執(zhí)行任務(wù)或計(jì)劃定期執(zhí)行任務(wù)。在 Timer

線程中執(zhí)行 TimerTask 事件,這意味著作為 TimerTask 執(zhí)行的任務(wù)必須是線程安全的。

Servlet 和 JavaServer Page 技術(shù)
Servlet 容器可以創(chuàng)建多個(gè)線程,在多個(gè)線程中同時(shí)調(diào)用給定 servlet,從而進(jìn)行多個(gè)請(qǐng)求。

因此 servlet 類必須是線程安全的。

RMI
遠(yuǎn)程方法調(diào)用(remote method invocation,RMI)工具允許調(diào)用其他 JVM 中運(yùn)行的

操作。實(shí)現(xiàn)遠(yuǎn)程對(duì)象最普遍的方法是擴(kuò)展 UnicastRemoteObject。例示 UnicastRemoteObject 時(shí),它是通過 RMI 調(diào)度器注冊(cè)的,該調(diào)度器可能創(chuàng)建一個(gè)或

多個(gè)線程,將在這些線程中執(zhí)行遠(yuǎn)程方法。因此,遠(yuǎn)程類必須是線程安全的。

正如所看到的,即使應(yīng)用程序沒有明確創(chuàng)建線程,也會(huì)發(fā)生許多可能會(huì)從其他線程調(diào)用類

的情況。幸運(yùn)的是,java.util.concurrent 中的類可以大大簡(jiǎn)化編寫線程安全類

的任務(wù)。

例子 —— 非線程安全 servlet


下列 servlet 看起來像無害的留言板 servlet,它保存每個(gè)來訪者的姓名。然而,該

servlet 不是線程安全的,而這個(gè) servlet 應(yīng)該是線程安全的。問題在于它使用

HashSet 存儲(chǔ)來訪者的姓名,HashSet 不是線程安全的類。

當(dāng)我們說這個(gè) servlet 不是線程安全的時(shí),是說它所造成的破壞不僅僅是丟失留言板

輸入。在最壞的情況下,留言板數(shù)據(jù)結(jié)構(gòu)都可能被破壞并且無法恢復(fù)。


public class UnsafeGuestbookServlet extends HttpServlet {

private Set visitorSet = new HashSet();

protected void doGet(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse)
throws ServletException, IOException {
String visitorName = httpServletRequest.getParameter("NAME");
if (visitorName != null)
visitorSet.add(visitorName);
}
}

通過將 visitorSet 的定義更改為下列代碼,可以使該類變?yōu)榫€程安全的: 

 private Set visitorSet = Collections.synchronizedSet(new HashSet());
JDK 1.2 中引入的 Collection 框架是一種表示對(duì)象集合的高度靈活的框架,

它使用

基本接口 List、SetMap。通過 JDK 提供每個(gè)集合的多次實(shí)現(xiàn)
HashMap、Hashtable、TreeMap、WeakHashMap、HashSet、TreeSet
Vector、ArrayListLinkedList 等等)。其中一些集合已經(jīng)是線程安
全的(HashtableVector),通過同步的封裝工廠
Collections.synchronizedMap()、synchronizedList() 
synchronizedSet()),其余的集合均可表現(xiàn)為線程安全的。
線程創(chuàng)建


線程最普遍的一個(gè)應(yīng)用程序是創(chuàng)建一個(gè)或多個(gè)線程,以執(zhí)行特定類型的任務(wù)。

Timer 類創(chuàng)建線

程來執(zhí)行 TimerTask 對(duì)象,Swing 創(chuàng)建線程來處理 UI 事件。在這兩種情況中,

在單獨(dú)線程

中執(zhí)行的任務(wù)都假定是短期的,這些線程是為了處理大量短期任務(wù)而存在的。

在其中每種情況中,這些線程一般都有非常簡(jiǎn)單的結(jié)構(gòu):


while (true) {
if (no tasks)
wait for a task;
execute the task;
}

通過例示從 Thread 獲得的對(duì)象并調(diào)用 Thread.start() 方法來創(chuàng)建線程。

可以用兩種方法創(chuàng)建線程:通過擴(kuò)展 Thread 和覆蓋 run() 方法,或者通過

實(shí)現(xiàn) Runnable 接口和使用 Thread(Runnable) 構(gòu)造函數(shù):


class WorkerThread extends Thread {
public void run() { /* do work */ }
}
Thread t = new WorkerThread();
t.start();

或者:


Thread t = new Thread(new Runnable() {
public void run() { /* do work */ }
}
t.start();
如何不對(duì)任務(wù)進(jìn)行管理


大多數(shù)服務(wù)器應(yīng)用程序(如 Web 服務(wù)器、POP 服務(wù)器、數(shù)據(jù)庫服務(wù)器或文件
服務(wù)器)代表遠(yuǎn)程客戶機(jī)處理請(qǐng)求,這些客戶機(jī)通常使用 socket 連接到服務(wù)器。
對(duì)于每個(gè)請(qǐng)求,通常要進(jìn)行少量處理(獲得該文件的代碼塊,并將其發(fā)送回
 socket),但是可能會(huì)有大量(且不受限制)的客戶機(jī)請(qǐng)求服務(wù)。 
用于構(gòu)建服務(wù)器應(yīng)用程序的簡(jiǎn)單化模型會(huì)為每個(gè)請(qǐng)求創(chuàng)建新的線程。下列代碼段
實(shí)現(xiàn)簡(jiǎn)單的 Web 服務(wù)器,它接受端口 80 的 socket 連接,并創(chuàng)建新的線程來
處理請(qǐng)求。不幸的是,該代碼不是實(shí)現(xiàn) Web 服務(wù)器的好方法,因?yàn)樵谥刎?fù)載條
件下它將失敗,停止整臺(tái)服務(wù)器.
class UnreliableWebServer {
public static void main(String[] args) {
ServerSocket socket = new ServerSocket(80);
while (true) {
final Socket connection = socket.accept();
Runnable r = new Runnable() {
public void run() {
handleRequest(connection);
}
};
// Don‘t do this!
new Thread(r).start();
}
}
}
當(dāng)服務(wù)器被請(qǐng)求吞沒時(shí),UnreliableWebServer 類不能很好地處理這種情況。
每次有請(qǐng)求時(shí),就會(huì)創(chuàng)建新的類。根據(jù)操作系統(tǒng)和可用內(nèi)存,可以創(chuàng)建的線程數(shù)
是有限的。不幸的是,您通常不知道限制是多少 —— 只有當(dāng)應(yīng)用程序因?yàn)?
OutOfMemoryError 而崩潰時(shí)才發(fā)現(xiàn)。

使用線程池解決問題



為任務(wù)創(chuàng)建新的線程并不一定不好,但是如果創(chuàng)建任務(wù)的頻率高,而平均任務(wù)持
續(xù)時(shí)間低,我們可以看到每項(xiàng)任務(wù)創(chuàng)建一個(gè)新的線程將產(chǎn)生性能(如果負(fù)載不可
預(yù)知,還有穩(wěn)定性)問題。 如果不是每項(xiàng)任務(wù)創(chuàng)建一個(gè)新的線程,則服務(wù)器應(yīng)
用程序必須采取一些方法來限制一次可以處理的請(qǐng)求數(shù)。這意味著每次需要啟動(dòng)
新的任務(wù)時(shí),它不能僅調(diào)用下列代碼。 

new Thread(runnable).start()
管理一大組小任務(wù)的標(biāo)準(zhǔn)機(jī)制是組合工作隊(duì)列線程池。工作隊(duì)列就是要處理的
任務(wù)的隊(duì)列,前面描述的 Queue 類完全適合。線程池是線程的集合,每個(gè)線程
都提取公用工作隊(duì)列。當(dāng)一個(gè)工作線程完成任務(wù)處理后,它會(huì)返回隊(duì)列,查看是
否有其他任務(wù)需要處理。如果有,它會(huì)轉(zhuǎn)移到下一個(gè)任務(wù),并開始處理。 
Executor 框架


java.util.concurrent 包中包含靈活的線程池實(shí)現(xiàn),但是更重要的是,
它包含用于管理實(shí)現(xiàn) Runnable 的任務(wù)的執(zhí)行的整個(gè)框架。該框架稱為
 Executor 框架。 
Executor 接口相當(dāng)簡(jiǎn)單。它描述將運(yùn)行 Runnable 的對(duì)象: 

public interface Executor {
void execute(Runnable command);
}
任務(wù)運(yùn)行于哪個(gè)線程不是由該接口指定的,這取決于使用的 Executor 的實(shí)現(xiàn)。
它可以運(yùn)行于后臺(tái)線程,如 Swing 事件線程,或者運(yùn)行于線程池,或者調(diào)用
線程,或者新的線程,它甚至可以運(yùn)行于其他 JVM!通過同步的 Executor 
接口提交任務(wù),從任務(wù)執(zhí)行策略中刪除任務(wù)提交。Executor 接口獨(dú)自關(guān)注任
務(wù)提交 —— 這是 Executor 實(shí)現(xiàn)的選擇,確定執(zhí)行策略。這使在部署時(shí)調(diào)整
執(zhí)行策略(隊(duì)列限制、池大小、優(yōu)先級(jí)排列等等)更加容易,更改的代碼最少。

Executor



更可靠的 Web 服務(wù)器 —— 使用 Executor
java.util.concurrent 包包含多個(gè) Executor 實(shí)現(xiàn),每個(gè)實(shí)現(xiàn)都實(shí)現(xiàn)不
同的執(zhí)行策略。什么是執(zhí)行策略?執(zhí)行策略定義何時(shí)在哪個(gè)線程中運(yùn)行任務(wù),
執(zhí)行任務(wù)可能消耗的資源級(jí)別(線程、內(nèi)存等等),以及如果執(zhí)行程序超載
該怎么辦。 執(zhí)行程序通常通過工廠方法例示,而不是通過構(gòu)造函數(shù)。Executors 
類包含用于構(gòu)造許多不同類型的 Executor 實(shí)現(xiàn)的靜態(tài)工廠方法:
  • Executors.newCachedThreadPool() 創(chuàng)建不限制大小線程池,但是當(dāng)以
  • 前創(chuàng)建的線程可以使用時(shí)將重新使用那些線程。如果沒有現(xiàn)有線程可用,將創(chuàng)建新的線
  • 程并將其添加到池中。使用不到 60 秒的線程將終止并從緩存中刪除。

  • Executors.newFixedThreadPool(int n) 創(chuàng)建線程池,其重新使用在不
  • 受限制的隊(duì)列之外運(yùn)行的固定線程組。在關(guān)閉前,所有線程都會(huì)因?yàn)閳?zhí)行過程中的失敗
  • 而終止,如果需要執(zhí)行后續(xù)任務(wù),將會(huì)有新的線程來代替這些線程。

  • Executors.newSingleThreadExecutor() 創(chuàng)建 Executor,其使用在不受
  • 限制的隊(duì)列之外運(yùn)行的單一工作線程,與 Swing 事件線程非常相似。保證順序執(zhí)行任務(wù),
  • 在任何給定時(shí)間,不會(huì)有多個(gè)任務(wù)處于活動(dòng)狀態(tài)。
class ReliableWebServer { 
Executor pool =
Executors.newFixedThreadPool(7);
public static void main(String[] args) {
ServerSocket socket = new ServerSocket(80);
while (true) {
final Socket connection = socket.accept();
Runnable r = new Runnable() {
public void run() {
handleRequest(connection);
}
};
pool.execute(r);
}
}
}
定制 ThreadPoolExecutor


Executors 中的 newFixedThreadPoolnewCachedThreadPool 工廠方法返回的 
Executor 是類 ThreadPoolExecutor 的實(shí)例,是高度可定制的。 
通過使用包含 ThreadFactory 變量的工廠方法或構(gòu)造函數(shù)的版本,可以定義池線程的創(chuàng)建。
ThreadFactory 是工廠對(duì)象,其構(gòu)造執(zhí)行程序要使用的新線程。使用定制的線程工廠,創(chuàng)建
的線程可以包含有用的線程名稱,并且這些線程是守護(hù)線程,屬于特定線程組或具有特定優(yōu)先級(jí)。 
下面是線程工廠的例子,它創(chuàng)建守護(hù)線程,而不是創(chuàng)建用戶線程: 

public class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
}

java.util.concurrent 中其他類別的有用的類也是同步工具。這組類相互協(xié)作,

控制一個(gè)或多個(gè)線程的執(zhí)

行流。

Semaphore、CyclicBarrierCountdownLatchExchanger 類都是同步工具

的例子。

每個(gè)類都有線程可以調(diào)用的方法,方法是否被阻塞取決于正在使用的特定同步

工具的狀態(tài)和規(guī)則。


本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
基于優(yōu)先級(jí)隊(duì)列java線程池
Java多線程
課堂筆記第八周
java.util.concurrent介紹A
Java Threads 多線程10分鐘參考手冊(cè)
Java并發(fā)編程73道面試題及答案 —— 面試穩(wěn)了
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服