當前位置:首頁 » 編程語言 » java並發包

java並發包

發布時間: 2022-09-25 10:47:48

『壹』 java並發包源碼怎麼讀

1. 各種同步控制工具的使用

1.1 ReentrantLock

ReentrantLock感覺上是synchronized的增強版,synchronized的特點是使用簡單,一切交給JVM去處理,但是功能上是比較薄弱的。在JDK1.5之前,ReentrantLock的性能要好於synchronized,由於對JVM進行了優化,現在的JDK版本中,兩者性能是不相上下的。如果是簡單的實現,不要刻意去使用ReentrantLock。

相比於synchronized,ReentrantLock在功能上更加豐富,它具有可重入、可中斷、可限時、公平鎖等特點。

首先我們通過一個例子來說明ReentrantLock最初步的用法:

package test;

import java.util.concurrent.locks.ReentrantLock;public class Test implements Runnable{ public static ReentrantLock lock = new ReentrantLock(); public static int i = 0;

@Override public void run() { for (int j = 0; j < 10000000; j++)
{ lock.lock(); try
{
i++;
} finally
{ lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
Thread t1 = new Thread(test);
Thread t2 = new Thread(test);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}

}

有兩個線程都對i進行++操作,為了保證線程安全,使用了ReentrantLock,從用法上可以看出,與synchronized相比,ReentrantLock就稍微復雜一點。因為必須在finally中進行解鎖操作,如果不在finally解鎖,有可能代碼出現異常鎖沒被釋放,而synchronized是由JVM來釋放鎖。

那麼ReentrantLock到底有哪些優秀的特點呢?

1.1.1 可重入

單線程可以重復進入,但要重復退出

lock.lock();
lock.lock();try{
i++;

}
finally{
lock.unlock();
lock.unlock();
}

由於ReentrantLock是重入鎖,所以可以反復得到相同的一把鎖,它有一個與鎖相關的獲取計數器,如果擁有鎖的某個線程再次得到鎖,那麼獲取計數器就加1,然後鎖需要被釋放兩次才能獲得真正釋放(重入鎖)。這模仿了synchronized的語義;如果線程進入由線程已經擁有的監控器保護的 synchronized 塊,就允許線程繼續進行,當線程退出第二個(或者後續)synchronized塊的時候,不釋放鎖,只有線程退出它進入的監控器保護的第一個synchronized塊時,才釋放鎖。

public class Child extends Father implements Runnable{ final static Child child = new Child();//為了保證鎖唯一
public static void main(String[] args) { for (int i = 0; i < 50; i++) { new Thread(child).start();
}
}
public synchronized void doSomething() {
System.out.println("1child.doSomething()");
doAnotherThing(); // 調用自己類中其他的synchronized方法
}
private synchronized void doAnotherThing() { super.doSomething(); // 調用父類的synchronized方法
System.out.println("3child.doAnotherThing()");
}
@Override
public void run() {
child.doSomething();
}
}class Father { public synchronized void doSomething() {
System.out.println("2father.doSomething()");
}
}

我們可以看到一個線程進入不同的synchronized方法,是不會釋放之前得到的鎖的。所以輸出還是順序輸出。所以synchronized也是重入鎖

輸出:

1child.doSomething()
2father.doSomething()
3child.doAnotherThing()
1child.doSomething()
2father.doSomething()
3child.doAnotherThing()
1child.doSomething()
2father.doSomething()
3child.doAnotherThing()
...

1.1.2.可中斷

與synchronized不同的是,ReentrantLock對中斷是有響應的。中斷相關知識查看[高並發Java 二] 多線程基礎

普通的lock.lock()是不能響應中斷的,lock.lockInterruptibly()能夠響應中斷。

我們模擬出一個死鎖現場,然後用中斷來處理死鎖

package test;import java.lang.management.ManagementFactory;import java.lang.management.ThreadInfo;import java.lang.management.ThreadMXBean;import java.util.concurrent.locks.ReentrantLock;public class Test implements Runnable{ public static ReentrantLock lock1 = new ReentrantLock(); public static ReentrantLock lock2 = new ReentrantLock(); int lock; public Test(int lock)
{ this.lock = lock;
} @Override
public void run()
{ try
{ if (lock == 1)
{
lock1.lockInterruptibly(); try
{
Thread.sleep(500);
} catch (Exception e)
{ // TODO: handle exception
}
lock2.lockInterruptibly();
} else
{
lock2.lockInterruptibly(); try
{
Thread.sleep(500);
} catch (Exception e)
{ // TODO: handle exception
}
lock1.lockInterruptibly();
}
} catch (Exception e)
{ // TODO: handle exception
} finally
{ if (lock1.isHeldByCurrentThread())
{
lock1.unlock();
} if (lock2.isHeldByCurrentThread())
{
lock2.unlock();
}
System.out.println(Thread.currentThread().getId() + ":線程退出");
}
} public static void main(String[] args) throws InterruptedException {
Test t1 = new Test(1);
Test t2 = new Test(2);
Thread thread1 = new Thread(t1);
Thread thread2 = new Thread(t2);
thread1.start();
thread2.start();
Thread.sleep(1000); //DeadlockChecker.check();
} static class DeadlockChecker
{ private final static ThreadMXBean mbean = ManagementFactory
.getThreadMXBean(); final static Runnable deadlockChecker = new Runnable()
{ @Override
public void run()
{ // TODO Auto-generated method stub
while (true)
{ long[] deadlockedThreadIds = mbean.findDeadlockedThreads(); if (deadlockedThreadIds != null)
{
ThreadInfo[] threadInfos = mbean.getThreadInfo(deadlockedThreadIds); for (Thread t : Thread.getAllStackTraces().keySet())
{ for (int i = 0; i < threadInfos.length; i++)
{ if(t.getId() == threadInfos[i].getThreadId())
{
t.interrupt();
}
}
}
} try
{
Thread.sleep(5000);
} catch (Exception e)
{ // TODO: handle exception
}
}

}
};
public static void check()
{
Thread t = new Thread(deadlockChecker);
t.setDaemon(true);
t.start();
}
}

}

上述代碼有可能會發生死鎖,線程1得到lock1,線程2得到lock2,然後彼此又想獲得對方的鎖。

我們用jstack查看運行上述代碼後的情況

下面舉個例子:

package test;import java.util.concurrent.CyclicBarrier;public class Test implements Runnable{ private String soldier; private final CyclicBarrier cyclic; public Test(String soldier, CyclicBarrier cyclic)
{ this.soldier = soldier; this.cyclic = cyclic;
} @Override
public void run()
{ try
{ //等待所有士兵到齊
cyclic.await();
dowork(); //等待所有士兵完成工作
cyclic.await();
} catch (Exception e)
{ // TODO Auto-generated catch block
e.printStackTrace();
}

} private void dowork()
{ // TODO Auto-generated method stub
try
{
Thread.sleep(3000);
} catch (Exception e)
{ // TODO: handle exception
}
System.out.println(soldier + ": done");
} public static class BarrierRun implements Runnable
{ boolean flag; int n; public BarrierRun(boolean flag, int n)
{ super(); this.flag = flag; this.n = n;
} @Override
public void run()
{ if (flag)
{
System.out.println(n + "個任務完成");
} else
{
System.out.println(n + "個集合完成");
flag = true;
}

}

} public static void main(String[] args)
{ final int n = 10;
Thread[] threads = new Thread[n]; boolean flag = false;
CyclicBarrier barrier = new CyclicBarrier(n, new BarrierRun(flag, n));
System.out.println("集合"); for (int i = 0; i < n; i++)
{
System.out.println(i + "報道");
threads[i] = new Thread(new Test("士兵" + i, barrier));
threads[i].start();
}
}

}

列印結果:

集合

士兵5: done士兵7: done士兵8: done士兵3: done士兵4: done士兵1: done士兵6: done士兵2: done士兵0: done士兵9: done10個任務完成

1.7 LockSupport

提供線程阻塞原語

和suspend類似

LockSupport.park();
LockSupport.unpark(t1);

與suspend相比不容易引起線程凍結

LockSupport的思想呢,和Semaphore有點相似,內部有一個許可,park的時候拿掉這個許可,unpark的時候申請這個許可。所以如果unpark在park之前,是不會發生線程凍結的。

下面的代碼是[高並發Java 二] 多線程基礎中suspend示例代碼,在使用suspend時會發生死鎖。

而使用LockSupport則不會發生死鎖。

另外

park()能夠響應中斷,但不拋出異常。中斷響應的結果是,park()函數的返回,可以從Thread.interrupted()得到中斷標志。

在JDK當中有大量地方使用到了park,當然LockSupport的實現也是使用unsafe.park()來實現的。

public static void park() { unsafe.park(false, 0L);
}

1.8 ReentrantLock 的實現

下面來介紹下ReentrantLock的實現,ReentrantLock的實現主要由3部分組成:

  • CAS狀態

  • 等待隊列

  • park()

  • ReentrantLock的父類中會有一個state變數來表示同步的狀態

  • /**

  • * The synchronization state.

  • */

  • private volatile int state;

  • 通過CAS操作來設置state來獲取鎖,如果設置成了1,則將鎖的持有者給當前線程

  • final void lock() { if (compareAndSetState(0, 1))

  • setExclusiveOwnerThread(Thread.currentThread()); else

  • acquire(1);

  • }

  • 如果拿鎖不成功,則會做一個申請

  • public final void acquire(int arg) { if (!tryAcquire(arg) &&

  • acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

  • selfInterrupt();

  • }

  • 首先,再去申請下試試看tryAcquire,因為此時可能另一個線程已經釋放了鎖。

    如果還是沒有申請到鎖,就addWaiter,意思是把自己加到等待隊列中去

    其間還會有多次嘗試去申請鎖,如果還是申請不到,就會被掛起

  • private final boolean parkAndCheckInterrupt() {

  • LockSupport.park(this); return Thread.interrupted();

  • }

  • 同理,如果在unlock操作中,就是釋放了鎖,然後unpark,這里就不具體講了。

    2. 並發容器及典型源碼分析

    2.1ConcurrentHashMap

    我們知道HashMap不是一個線程安全的容器,最簡單的方式使HashMap變成線程安全就是使用Collections.synchronizedMap,它是對HashMap的一個包裝

  • public static Map m=Collections.synchronizedMap(new HashMap());

  • 同理對於List,Set也提供了相似方法。

    但是這種方式只適合於並發量比較小的情況。

    我們來看下synchronizedMap的實現

    它會將HashMap包裝在裡面,然後將HashMap的每個操作都加上synchronized。

    由於每個方法都是獲取同一把鎖(mutex),這就意味著,put和remove等操作是互斥的,大大減少了並發量。

    下面來看下ConcurrentHashMap是如何實現的

    在ConcurrentHashMap內部有一個Segment段,它將大的HashMap切分成若干個段(小的HashMap),然後讓數據在每一段上Hash,這樣多個線程在不同段上的Hash操作一定是線程安全的,所以只需要同步同一個段上的線程就可以了,這樣實現了鎖的分離,大大增加了並發量。

    在使用ConcurrentHashMap.size時會比較麻煩,因為它要統計每個段的數據和,在這個時候,要把每一個段都加上鎖,然後再做數據統計。這個就是把鎖分離後的小小弊端,但是size方法應該是不會被高頻率調用的方法。

    在實現上,不使用synchronized和lock.lock而是盡量使用trylock,同時在HashMap的實現上,也做了一點優化。這里就不提了。

    2.2BlockingQueue

    BlockingQueue不是一個高性能的容器。但是它是一個非常好的共享數據的容器。是典型的生產者和消費者的實現。

『貳』 Java培訓都學什麼內容

Java培訓主要學的內容如下:

1) Java SE核心技術:Java語言核心編程技術。
2) Java EE Web開發技術:Servlet/JSP/JavaBean編程技術、MVC模式。
3) Java EE流行框架技術:Struts2/Hibernate3/Spring2流行框架。
4) Java EE企業開發通用組件:log4j、JFreeChart、分頁、目錄樹等。
5) UML與設計模式:統一建模語言UML、經典設計模式。
6) 富客戶端(RIA)開發:AJAX、Flex等。

java是一門面向對象的編程語言,java語言具有功能強大和簡單易用兩個特徵,具有簡單性、面向對象、分布式等特點,可以編寫桌面應用程序、Web應用程序、分布式系統和嵌入式系統應用程序等。

想要了解更多有關Java培訓的相關信息,推薦咨詢千鋒教育。北京千鋒互聯科技有限公司(下面簡稱「千鋒教育」),成立於2011年1月,立足於職業教育培訓領域,公司現有教育培訓、高校服務、企業服務三大業務板塊。教育培訓業務分為大學生技能培訓和職後技能培訓;高校服務業務主要提供校企合作全解決方案與定製服務;企業服務業務主要為企業提供專業化綜合服務。

『叄』 java並發包有哪些類

1、CyclicBarrier

一個同步輔助類,允許一組線程相互等待,直到這組線程都到達某個公共屏障點。該barrier在釋放等待線程後可以重用,因此稱為循環的barrier。

來個示例:

[java]view plain

  • packagetest;

  • importjava.util.concurrent.CyclicBarrier;

  • importjava.util.concurrent.ExecutorService;

  • importjava.util.concurrent.Executors;

  • publicclassRecipes_CyclicBarrier{

  • =newCyclicBarrier(10);

  • publicstaticvoidmain(String[]args){

  • ExecutorServiceexecutor=Executors.newCachedThreadPool();//FixedThreadPool(10);

  • for(inti=1;i<=10;i++){

  • executor.submit(newThread(newRunner(i+"號選手")));

  • }

  • executor.shutdown();

  • }

  • }

  • classRunnerimplementsRunnable{

  • privateStringname;

  • publicRunner(Stringname){

  • this.name=name;

  • }

  • @Override

  • publicvoidrun(){

  • System.out.println(name+"准備好了。");

  • try{

  • Recipes_CyclicBarrier.barrier.await();//此處就是公共屏障點,所有線程到達之後,會釋放所有等待的線程

  • }catch(Exceptione){

  • }

  • System.out.println(name+"起跑!");

  • }

  • }

  • 2、CountDownLatch

    CountDownLatch和CyclicBarrier有點類似,但是還是有些區別的。CountDownLatch也是一個同步輔助類,它允許一個或者多個線程一直等待,直到正在其他線程中執行的操作完成。它是等待正在其他線程中執行的操作,並不是線程之間相互等待。CountDownLatch初始化時需要給定一個計數值,每個線程執行完之後,必須調用countDown()方法使計數值減1,直到計數值為0,此時等待的線程才會釋放。

    來個示例:

    [java]view plain

  • packagetest;

  • importjava.util.concurrent.CountDownLatch;

  • importjava.util.concurrent.CyclicBarrier;

  • importjava.util.concurrent.ExecutorService;

  • importjava.util.concurrent.Executors;

  • publicclassCountDownLatchDemo{

  • =newCountDownLatch(10);//初始化計數值

  • publicstaticvoidmain(String[]args){

  • ExecutorServiceexecutor=Executors.newCachedThreadPool();//FixedThreadPool(10);

  • for(inti=1;i<=10;i++){

  • executor.submit(newThread(newRunner1(i+"號選手")));

  • }

  • executor.shutdown();

  • }

  • }

  • {

  • privateStringname;

  • publicRunner1(Stringname){

  • this.name=name;

  • }

  • @Override

  • publicvoidrun(){

  • System.out.println(name+"准備好了。");

  • CountDownLatchDemo.countDownLatch.countDown();//計數值減1

  • try{

  • CountDownLatchDemo.countDownLatch.await();

  • }catch(Exceptione){

  • }

  • System.out.println(name+"起跑!");

  • }

  • }

  • 3、CopyOnWriteArrayList & CopyOnWriteArraySet

    CopyOnWriteArrayList & CopyOnWriteArraySet是並發容器,適合讀多寫少的場景,如網站的黑白名單設置。缺點是內存佔用大,數據一致性的問題,CopyOnWrite容器只能保證數據最終的一致性,不能保證數據實時一致性。鑒於它的這些缺點,可以使用ConcurrentHashMap容器。

    實現原理:新增到容器的數據會放到一個新的容器中,然後將原容器的引用指向新容器,舊容器也會存在,因此會有兩個容器佔用內存。我們也可以用同樣的方式實現自己的CopyOnWriteMap。

    4、ConcurrentHashMap

    ConcurrentHashMap同樣是一個並發容器,將同步粒度最小化。

    實現原理:ConcurrentHashMap默認是由16個Segment組成,每個Segment由多個Hashtable組成,數據變更需要經過兩次哈希演算法,第一次哈希定位到Segment,第二次哈希定位到Segment下的Hashtable,容器只會將單個Segment鎖住,然後操作Segment下的Hashtable,多個Segment之間不受影響。如果需要擴容不是對Segment擴容而是對Segment下的Hashtable擴容。雖然經過兩次哈希演算法會使效率降低,但是比鎖住整個容器效率要高得多。

    5、BlockingQueue

    BlockingQueue只是一個介面,它的實現類有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、DelayQueue、LinkedBlockingDeque。

    ArrayBlockingQueue:由數據支持的有界阻塞隊列。

    LinkedBlockingQueue:基於鏈接節點、范圍任意的阻塞隊列。

    PriorityBlockingQueue:無界阻塞隊列。

    SynchronousQueue:一種阻塞隊列,其中每個插入操作必須等待另一個線程的對應移除操作。

    DelayQueue:Delayed元素的一個無界阻塞隊列。

    LinkedBlockingDeque:基於鏈接節點、范圍任意的雙端阻塞隊列,可以在隊列的兩端添加、移除元素。

    6、Lock

    Lock分為公平鎖和非公平鎖,默認是非公平鎖。實現類有ReetrantLock、ReetrantReadWriteLock,都依賴於AbstractQueuedSynchronizer抽象類。ReetrantLock將所有Lock介面的操作都委派到Sync類上,Sync有兩個子類:NonFairSync和FaiSync,通過其命名就能知道分別處理非公平鎖和公平鎖的。AbstractQueuedSynchronizer把所有請求構成一個CLH隊列,這里是一個虛擬隊列,當有線程競爭鎖時,該線程會首先嘗試是否能獲取鎖,這種做法對於在隊列中等待的線程來說是非公平的,如果有線程正在Running,那麼通過循環的CAS操作將此線程增加到隊尾,直至添加成功。

    7、Atomic包

    Atomic包下的類實現了原子操作,有對基本類型如int、long、boolean實現原子操作的類:AtomicInteger、AtomicLong、AtomicBoolean,如果需要對一個對象進行原子操作,也有對對象引用進行原子操作的AtomicReference類,還有對對象數組操作的原子類:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。原子操作核心思想是CAS操作,然後調用底層操作系統指令來實現。

『肆』 Java並發包中的幾種ExecutorService

FixedThreadPool模式會使用一個優先固定數目的線程來處理若干數目的任務。規定數目的線程處理所有任務,一旦有線程處理完了任務就會被用來處理新的任務(如果有的話)。這種模式與上面的CachedThreadPool是不同的,CachedThreadPool模式下處理一定數量的任務的線程數目是不確定的。而FixedThreadPool模式下最多的線程數目是一定的。 採用FixedThreadPool模式編寫客戶端程序如下:packagenet.jerryblog.concurrent;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassFixedThreadPool{publicstaticvoidmain(String[]args){ //三個線程來執行五個任務 ExecutorServiceexec=Executors.newFixedThreadPool(3);for(inti=0;i<5;i++){exec.execute(newLiftOff());}exec.shutdown();}} 3.SingleThreadExecutor模式 SingleThreadExecutor模式只會創建一個線程。它和FixedThreadPool比較類似,不過線程數是一個。如果多個任務被提交給SingleThreadExecutor的話,那麼這些任務會被保存在一個隊列中,並且會按照任務提交的順序,一個先執行完成再執行另外一個線程。 SingleThreadExecutor模式可以保證只有一個任務會被執行。這種特點可以被用來處理共享資源的問題而不需要考慮同步的問題。 SingleThreadExecutor模式編寫的客戶端程序如下:packagenet.jerryblog.concurrent;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;{publicstaticvoidmain(String[]args){ ExecutorServiceexec=Executors.newSingleThreadExecutor();for(inti=0;i<2;i++){exec.execute(newLiftOff());}}}這種模式下執行的結果如下: #0(9)#0(8)#0(7)#0(6)#0(5)#0(4)#0(3)#0(2)#0(1)#0(LiftOff!) 第一個任務執行完了之後才開始執行第二個任務。

『伍』 ArrayList詳解,自動擴容原理




ArrayList<E>:說明ArrayList支持泛型。
extends AbstractList<E> :繼承了AbstractList。AbstractList提供List介面的骨幹實現,以最大限度地減少「隨機訪問」數據存儲(如ArrayList)實現Llist所需的工作。
implements List<E>:實現了List。實現了所有可選列表操作。
implements RandomAccess:表明ArrayList支持快速(通常是固定時間)隨機訪問。此介面的主要目的是允許一般的演算法更改其行為,從而在將其應用到隨機或連續訪問列表時能提供良好的性能。
implements Cloneable:表明其可以調用clone()方法來返回實例的field-for-field拷貝。
implements java.io.Serializable:表明該類具有序列化功能。有序列化功能
下面來看一些比較重要的參數:

ArrayList的實際大小(數組包含真正的元素個數)

執行完構造方法時還是一個空數組,等到add方法執行的時候則會初始化容量為10;

自己穿入想要的容量參數,對容量進行判斷如果容量小於零,則會拋出異常,否則會創建一個容量為initialCapacity的空ArrayList

構造一個包含指定 collection 的元素的列表,這些元素是按照該 collection 的迭代器返回它們的順序排列的。

先來看其中的add()方法:

add方法首先會調用ensureCapacityInternal(size+1)方法,

ensureCapacityInternal(size+1)方法是用來進行容量檢查,決定擴容的想要的最小容量,舉個例子,第一次擴容的時候,size默認為0則minCapacity(即想要的最小容量)為1,執行完Math.max語句minCapacity就變為10,這個時候也就是進行空構造第一次add的情況,當ensureCapacityInternal(size+1)傳入的參數小於默認參數的時候,就把默認參數當做想要的最小容量,如果大於默認參數就把你想要的參數當做想要的最小容量

這個方法是用來判斷是否擴容,如果你想要的最小容量大於數組長度則會調用grow方法進行擴容

通過grow方法可以看到新容量為當前數組容量的1.5倍,然後進行判斷,如果理論擴容後新的容量小於小於你想要的最小容量(但我覺得這種情況不太可能會出現,因為為了節省空間,假如當前容量為10,只會傳入11來和擴容後的進行比較因此我自己認為不會出現if為真的情況)真正的實現擴容其實是Arrays.方法,就是復制數組實現擴容,

但是如果出現了if為真的情況,從這個方法中可以看到數組的理論最大值為Integer的最大值減去8,但是如果你想要的最小容量已經大於數組的理論最大值,則會進行大容量分配為Integer的最大值至此擴容結束,

下面粗略的談一下快速失敗機制(因為對線程還沒有一個好的認識)

fail-fast是怎麼產生的。步驟如下:

新建了一個ArrayList,名稱為arrayList。
向arrayList中添加內容
新建一個「線程a」,並在「線程a」中通過Iterator反復的讀取arrayList的值。
新建一個「線程b」,在「線程b」中刪除arrayList中的一個「節點A」。
這時,就會產生有趣的事件了。
在某一時刻,「線程a」創建了arrayList的Iterator。此時「節點A」仍然存在於arrayList中,創建arrayList時,expectedModCount = modCount(假設它們此時的值為N)。
在「線程a」在遍歷arrayList過程中的某一時刻,「線程b」執行了,並且「線程b」刪除了arrayList中的「節點A」。「線程b」執行remove()進行刪除操作時,在remove()中執行了「modCount++」,此時modCount變成了N+1!

「線程a」接著遍歷,當它執行到next()函數時,調用checkForComodification()比較「expectedModCount」和「modCount」的大小;而「expectedModCount=N」,「modCount=N+1」,這樣,便拋出異常,產生fail-fast事件。

至此,我們就完全了解了fail-fast是如何產生的!
即,當多個線程對同一個集合進行操作的時候,某線程訪問集合的過程中,該集合的內容被其他線程所改變(即其它線程通過add、remove、clear等方法,改變了modCount的值);這時,就會拋出異常,產生fail-fast事件。

方法1
在單線程的遍歷過程中,如果要進行remove操作,可以調用迭代器的remove方法而不是集合類的remove方法。看看ArrayList中迭代器的remove方法的源碼:

可以看到,該remove方法並不會修改modCount的值,並且不會對後面的遍歷造成影響,因為該方法remove不能指定元素,只能remove當前遍歷過的那個元素,所以調用該方法並不會發生fail-fast現象。該方法有局限性。
例子:

方法2
使用java並發包(java.util.concurrent)中的類來代替ArrayList 和hashMap。
比如使用 CopyOnWriterArrayList代替ArrayList,CopyOnWriterArrayList在是使用上跟ArrayList幾乎一樣,CopyOnWriter是寫時復制的容器(COW),在讀寫時是線程安全的。該容器在對add和remove等操作時,並不是在原數組上進行修改,而是將原數組拷貝一份,在新數組上進行修改,待完成後,才將指向舊數組的引用指向新數組,所以對於CopyOnWriterArrayList在迭代過程並不會發生fail-fast現象。但 CopyOnWrite容器只能保證數據的最終一致性,不能保證數據的實時一致性。
對於HashMap,可以使用ConcurrentHashMap,ConcurrentHashMap採用了鎖機制,是線程安全的。在迭代方面,ConcurrentHashMap使用了一種不同的迭代方式。在這種迭代方式中,當iterator被創建後集合再發生改變就不再是拋出,取而代之的是在改變時new新的數據從而不影響原有的數據 ,iterator完成後再將頭指針替換為新的數據 ,這樣iterator線程可以使用原來老的數據,而寫線程也可以並發的完成改變。即迭代不會發生fail-fast,但不保證獲取的是最新的數據。

『陸』 有哪些Java web里的並發框架,都有哪些

一、並發是一種需求,以下先介紹一下javaweb對於高並發的處理思路:

1、synchronized 關鍵字

可用來給對象和方法或者代碼塊加鎖,當它鎖定一個方法或者一個代碼塊的時候,同一時刻最多隻有一個線程執行這段代碼。可能鎖對象包括: this, 臨界資源對象,Class 類對象

2、同步方法

同步方法鎖定的是當前對象。當多線程通過同一個對象引用多次調用當前同步方法時, 需同步執行。

3、同步代碼塊

同步代碼塊的同步粒度更加細致,是商業開發中推薦的編程方式。可以定位到具體的同步位置,而不是簡單的將方法整體實現同步邏輯。在效率上,相對更高。

A)鎖定臨界對象

同步代碼塊在執行時,是鎖定 object 對象。當多個線程調用同一個方法時,鎖定對象不變的情況下,需同步執行。

B)鎖定當前對象

4、鎖的底層實現

Java 虛擬機中的同步(Synchronization)基於進入和退出管程(Monitor)對象實現。同步方法 並不是由 monitor enter 和 monitor exit 指令來實現同步的,而是由方法調用指令讀取運行時常量池中方法的 ACC_SYNCHRONIZED 標志來隱式實現的。

5、鎖的種類

Java 中鎖的種類大致分為偏向鎖,自旋鎖,輕量級鎖,重量級鎖。

鎖的使用方式為:先提供偏向鎖,如果不滿足的時候,升級為輕量級鎖,再不滿足,升級為重量級鎖。自旋鎖是一個過渡的鎖狀態,不是一種實際的鎖類型。

鎖只能升級,不能降級。

6、volatile 關鍵字

變數的線程可見性。在 CPU 計算過程中,會將計算過程需要的數據載入到 CPU 計算緩存中,當 CPU 計算中斷時,有可能刷新緩存,重新讀取內存中的數據。在線程運行的過程中,如果某變數被其他線程修改,可能造成數據不一致的情況,從而導致結果錯誤。而 volatile 修飾的變數是線程可見的,當 JVM 解釋 volatile 修飾的變數時,會通知 CPU,在計算過程中, 每次使用變數參與計算時,都會檢查內存中的數據是否發生變化,而不是一直使用 CPU 緩存中的數據,可以保證計算結果的正確。

更多、此外還有很多細節需要通過學習去了解和完善,此處就不一一列舉了。

二、並發框架

並發框架很多,如ExecutorService、RxJava、Disruptor、Akka等,具體選擇哪個(或者都不選擇)是根據項目需求選擇的,框架本身的差異並不大,基本都是如下模式

『柒』 《Java並發編程核心方法與框架高洪岩》pdf下載在線閱讀全文,求百度網盤雲資源

《Java並發編程核心方法與框架高洪岩》網路網盤pdf最新全集下載:
鏈接: https://pan..com/s/1IelP2YEUrDDE4wPSvpNH3g

?pwd=xxn5 提取碼: xxn5
簡介:全書共10章。第1章講解了線程間的同步性,以及線程間的傳輸數據控制,即Semaphore和Exchanger類的使用。第2章介紹了在同步處理上更加靈活的工具類CountDownLatch和CyclicBarrier,詳細到每個類的API的具體使用與應用場景。第3章是第2章的升級,由於CountDownLatch和CyclicBarrier類都有相應的弊端,所以在JDK 1.7中新增加了Phaser類來解決這些缺點,該類是熟練掌握JDK並發包的必要知識點。第4章是讀者應重點掌握的Executor介面與ThreadPoolExecutor線程池,能有效地提高程序運行效率,更好地統籌線程執行的相關任務。第5章講解Future和Callable的使用,解決線程需要返回值的情況。第6章介紹Java並發包中的CompletionService的使用,因為可以以非同步的方式獲得任務執行的結果,所以該介面可以增強程序運行效率。第7章介紹介面ExecutorService,該介面提供了若干工具方法來方便執行並發業務。第8章主要介紹ScheledExecutorService的使用,以掌握如何將計劃任務與線程池結合使用。第9章主要介紹Fork-Join分治編程,以提升多核CPU的優勢,加快程序運行效率。第10章主要介紹並發集合框架,利用好並發框架,事半功倍。

『捌』 Java培訓能學到哪些知識

Java培訓能學到哪些知識?目前市面上的Java培訓機構非常多,不同的Java培訓機構我們學到的知識點可能也會有所區別,學習Java的小夥伴可以在招聘公告上看一下具體的Java工程師的照片需求,關於Java培訓其實除了自己努力基本上由Java培訓機構控制。

參加Java培訓能學到知識嗎?Java培訓學習能不能學到知識,主要有一下幾點決定的:

第一、自己在Java培訓班的學習心態有沒有放正,學習是否足夠的努力,對於不懂的問題是否能夠虛心的請教;

第二、目前網上的Java學習資料也是比較多的,在學習之餘也可以在網上進行學習,擴展自己是知識;

第三、Java培訓班的師資和課程內容如何,老師是否足夠強,能夠把知識傳遞給學員,課程是否比較豐富;

學習是一件比較費時間的事情,不管是自學還是Java培訓,都是需要學員有足夠的信心和努力才能更好是學習。

在昆明北大青鳥參加Java培訓會學到哪些知識點呢?下面小編簡單概要一下:

第一階段、Java設計和編程思想

1、Java語言基礎

Java語言、Java環境變數、變數、運算符、表達式、分支語句、循環語句、數組、數組應用,行業規范。雙色球抽獎程序實現。

2、Java面向對象

類、對象、屬性、方法、構造、封裝、繼承、多態、重寫、重載、訪問許可權控制符、this、super、static、單例設計模式、final、抽象類和介面、模板設計模式、內部類。

3、JavaSE核心類庫

Java核心類、Java字元串、日期處理、包裝類、集合、數據結構、異常和異常處理、JavaIQ、多線程編程、線程同步機制、並發包、JAVA網路編程、Java泛型、Java反射機制。

4、Java設計

設計原則、設計模式、常見演算法、Java新特性、Maven使用SVN版本管理。

第二階段、資料庫技術和Web基礎

(H5)

1、Oracle資料庫開發

SQL語句、SQL語句原理、SQL語句優化、表、視圖、序列、索引、Oracle數據字典、Oracle資料庫PL/SQL開發、資料庫設計原則。

2、JDBC

JDBC核心API、JDBC優化技術(緩存技術、批處理技術、資料庫連接池)。

3、XML

XML語法、XML解析(SAX、DOM、Dom4j)。

4、HTML5(H5)Web前端技術

(H5/CSS3/JS)

基本文檔結構、鏈接、列表、表格、表單;CSS基礎語法、盒子模型、浮動布局、定位;JavaScript語言基礎、DOM編程、事件模型等。

5、Jquery

HTML5(H5)JQuery、JQuery對象、元素選擇、DOM、操作、CSS操作、動畫效果、JQuery插件。

6、AJAX框架

Ajax基礎、XHR對象、Ajax設計模式、JSON技術、RESTFUL技術。

第三階段、JAVAWeb技術和主流框架(SSH)

1、JSP&Serviet

JSP語法、JSP標記、自定義標記、JSTL和EL表達式、JSP新特性、MVC設計模式、Service生命周期及Serviet伺服器、Serviet過濾器和監聽器、Tomcat配置和部署。

2、Spring

SpringIoc、Ioc注入技巧、對象高級配裝配(自動裝配、模板裝配、組件掃描特性、FactoryBean、對象生命周期)、Spring、AOP、原理、Aspectj、SpringJDBC支持

3、MyBatis

MyBatis映射基礎,DQL映射,DML映射,結果集映射,高級動態SQL映射,SqlSession的使用,SpringMyBatis整合

4、Redis

Redis原理、Redis命令、JavaRedisAPI、SpringRedis整合、Redis集群和緩存

5、Nginx

Nginx原理、Nginx環境、Nginx、虛擬機、Nginx反向代理、Tomcat伺服器集成、NginxURL重寫、Session共享技術

Struts2&Hibernate

6、Struts2控制流程、OgnI、Action、Interceptor、Result、FreeMarker、Struts2標記庫、Struts2擴展、Strtus2應用、HibemateAPI、Hibemate實體映射技術、Hibemate關系映射技巧、HQL查詢、Hibernate緩存技術、SSH整合

第四階段、大數據技術(Hadoop和Spark)

1、Hadoop

Hadoop基礎和環境搭建,HDFS體系結構、MapRece;Hadoop的集群模式、HDFS聯盟、利用ZooKeeper來實現Hadoop集群的HA(高可用性)功能,Yarn的任務調度機制,ApacheHive,Pig數據處理,集成Hadoop和Sqoop、Flume以及ApacheKafKa來實現數據的交換,安裝部署HBase,Stomm

2、Scala語言

Scala環境搭建、Scala基礎語法、模式匹配、重載與構造器、MapRece、元組、繼承、StringContext,OptionSomeNone,Tuple;集合方法和運算,future對象同步處理和非同步處理返回結果

3、Spark

Spark和Hadoop已成為目前大數據處理領域的核心框架。課程體系詳細講解Spark搭建,Spark-shell的使用,Spark-submit提交應用,Spark的內核設計和實現,並對內核中的實現架構、運行原理進行詳細的講解;Spark生態習題中的各個組件,包括:SparkCore,SharkSQL和SparkStreaming等等。

以上內容是關於參加Java培訓可以學習到哪些知識點的內容概要,如果你也想參加Java培訓,一定要選擇靠譜的Java培訓機構,或者來昆明北大青鳥參加Java培訓班免費試聽課程可能對於學習Java的小夥伴有所幫助。

免責聲明:內容來源於公開網路,若涉及侵權聯系盡快刪除!

熱點內容
微信小程序游戲如何設置密碼 發布:2025-01-02 01:01:27 瀏覽:75
php跨域請求 發布:2025-01-02 01:01:24 瀏覽:784
5復式演算法 發布:2025-01-02 01:00:00 瀏覽:544
androidtts 發布:2025-01-02 00:59:59 瀏覽:74
監控訪問網址 發布:2025-01-02 00:57:15 瀏覽:332
堡壘機php 發布:2025-01-02 00:56:30 瀏覽:51
禁止網頁腳本 發布:2025-01-02 00:56:30 瀏覽:808
java培訓班入門 發布:2025-01-02 00:56:23 瀏覽:228
易語言封包攔截源碼 發布:2025-01-02 00:50:44 瀏覽:880
android編譯資源 發布:2025-01-02 00:48:37 瀏覽:207