歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java常用高級線程操作

Java常用高級線程操作

日期:2017/3/1 9:29:11   编辑:Linux編程

針對Java線程操作一直不太明白,今天找了一本高級教材,有專門介紹Java7支持的線程操作,稍微記錄一下各種類和使用條件

1.synchronized對象鎖

使用synchronized來鎖定一個對象,但是使用在類的方法中的時候會造成整個類的對象被鎖,因此對於其他沒有此關鍵字的標記也無法被其他線程操作。

synchronized可以鎖定任意代碼塊,可以鎖定任意對對象作為代碼塊的鎖。

2.volatile進行線程同步

volatile作為一個在內存和線程之間同步變量的關鍵字,不會再本地保存變量的二次拷貝。

3.ReentrantLock超時鎖的一個實現,可以實現鎖住代碼塊

在此類對象的.lock()和unlock()之間的代碼塊是被鎖定的塊,其下面的方法
lock.tryLock(10, TimeUnit.SECONDS);

可以用來指定超時時間。

4.阻塞隊列

這個是針對消費/生產問題的一個實現,一般使用LinkedBlockingQueue來指定具有無限容量的隊列,ArrayBlockingQueue是有界的阻塞隊列,

還有一個叫LinkedTransferQueue的實現,但是不是太明白書中的例子,應該是一種按需的隊列,就是如果隊列中有等待使用數據的線程,那麼插入數據的線程一旦啟動,就會產生需要的所有數據,而一旦沒有等待/請求數據的線程,就不產生數據。

5.同步器

信號量Semaphore這個類是用來生成信號量的,信號量的所謂機制就是如果信號量標記有正在處理的事件的時候,所有請求都被駁回,但是如果有空閒就接受請求。

看我寫的小例子:

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
public static void main(String[] args){
ExecutorService executorService = Executors.newFixedThreadPool(10);
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return new AtomicInteger(1).incrementAndGet();
}
};

Semaphore semaphore = new Semaphore(4,true);

try {
while (true) {
if (semaphore.tryAcquire(2, TimeUnit.SECONDS)) {
Future<Integer> future = executorService.submit(callable);
System.out.println(future.get());
}
}
}catch (InterruptedException e){

}catch (ExecutionException e){

}finally {
executorService.shutdown();
}
}
}

看到的是ExecutorService創建了10個的線程池(姑且稱為線程池),但是信號量是四個,那麼執行的時候只能看到四個輸出;


import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
public static void main(String[] args){
ExecutorService executorService = Executors.newFixedThreadPool(10);
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return new AtomicInteger(1).incrementAndGet();
}
};

Semaphore semaphore = new Semaphore(4,true);

try {
while (true) {
if (semaphore.tryAcquire(2, TimeUnit.SECONDS)) {
Future<Integer> future = executorService.submit(callable);
System.out.println(future.get());
}
semaphore.release();
}
}catch (InterruptedException e){

}catch (ExecutionException e){

}finally {
executorService.shutdown();
}
}
}

這段是加上了一個叫release的semaphore的方法,此方法釋放一個信號量許可,並返回給semaphore。

6.屏障

作為屏障的描述:是一個節點,這個節點是一個會和點,所有操作執行完畢之後都會轉到此位置,也就是說所有已經完成任務的線程都要等到其他線程完成,者有點像守護線程的概念。CyclicBarrier實現了屏障,它的構造方法指定一個數字和一個Runnable對象,數字是它調度指揮的線程的數目,Runnable是所有線程都結束之後CyclicBarrier執行的操作,

這個可以解決並行的一些算法運算,那個Runnable就是用來合並結果的(使用分治法思想)。

7.Callable,Future接口

這兩個對象都是能夠返回縣城運行結果的,Callable是被ExecutorService來執行的,Service的submit返回一個Future對象,可以使用它的get方法返回Callable 的運行結果,但是注意只有線程運行完畢之後Future才能有值可以返回

FutureTask是一個既實現Runnable又實現了Future接口的對象,既可以用他的run方法,又可以被submit

8.Executors

這個類的一系列的靜態方法來創建線程池並返回ExecutorService對象,newFixedThreadPoll是創建固定大小的線程池,newCacheThreadPool是創建60s之後自動銷毀的線程池,這個方便了在小段時間時線程數變化比較大的時候可以節省時間和內存。

newSingleThreadExecutor是創建 一個可以重用的線程。

newScheduledThreadPool創建一個指定大小的線程池,不同的是這個線程池執行線程的操作時按照時序來的,可以指定延遲和次數,可以通過返回的ScheduledExecutorService對象的scheduleAtFixedRate指定一個runnable還有其首次執行的延遲和之後兩次調用之間的延遲

9.ForkJoinPool和ForkJoinTask

這兩個也是一個用來創建線程池的方法,但是不同的是它們執行的線程可以被合並結果,但是他們執行的任務對象就使用其抽象子類,ForkJoinTask的實現抽象子類:RecursiveTask和RecursiveAction。

前者是可以返回結果,後者是無法返回結果的。計算要實現在compare實現的方法中。執行任務之後可以調用ForkJoinPool的invoke方法來提交一個任務,還有一個名為invokeAll()的方法,但是這個方法如何使用我還不是很了解,因為這個All方法調用的 參數是一個Callable對象集合而非ForkJoinTask。

10.線程安全的隨機數生成ThreadLocalRandom類

一般情況下使用它的靜態方法就可以生成,比如:
ThreadLocalRandom.current().nextLong(100);

生成的是以0為下限和100的上限的隨機數。

這個應當是一個線程安全的隨機數生辰器,因此可以考慮在並行運算中使用它。

Copyright © Linux教程網 All Rights Reserved