編輯:關於Android編程
21. 實現多線程的兩種方法
實現Runnable接口:實際工作中,幾乎所有的多線程應用都用實現Runnable這種方式。22. 線程同步的方法
synchronized關鍵字和Lock:當使用線程來同時運行多個任務時,可以通過使用鎖(互斥)來同步兩個任務的行為,從而使得一個任務不會干涉另一個任務的資源。也就是說,如果兩個任務在交替著步入某項共享資源,你可以使用互斥來使得任何時刻只有一個任務可以訪問這項資源。
synchronized:在資源競爭不是很激烈的情況下,Synchronized的性能要優於ReetrantLock,但是在資源競爭很激烈的情況下,Synchronized的性能會下降幾十倍,但是ReetrantLock的性能能維持常態;在資源競爭不是很激烈的情況下,偶爾會有同步的情形下,synchronized是很合適的。原因在於,編譯程序通常會盡可能的進行優化synchronize,另外可讀性非常好,不管用沒用過5.0多線程包的程序員都能理解。 ReentrantLock:ReentrantLock 擁有Synchronized相同的並發性和內存語義,此外還多了 鎖投票,定時鎖等候和中斷鎖等候。ReentrantLock提供了多樣化的同步,比如有時間限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在資源競爭不激烈的情形下,性能稍微比synchronized差點點。但是當同步非常激烈的時候,synchronized的性能一下子能下降好幾十倍。而ReentrantLock確還能維持常態。Object的方法wait()和notify()或者Condition的await()和signal()方法:任務彼此之間協作一起去解決某個問題,在解決這個問題中,由於某些部分必須在其他部分被解決之前解決。
wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock。會在等待外部世界產生變化時將任務掛起,並且只有在notify或notifyAll發生時,這個任務才會被喚醒病區檢查所產生的變化。因此,wait()提供了一種在任務之間對活動同步的方式。 sleep():使一個正在運行的線程處於睡眠狀態,是Thread的一個靜態方法,調用此方法需要捕捉InterruptedException異常,沒有釋放鎖。 notify():在眾多等待同一個鎖的任務中只有一個會被喚醒。注意的是在調用此方法時,並不能確切的喚醒某一個等待的線程,而是有JVM確定喚醒哪個線程,而不是按優先級。 notifyAll():將喚醒所有正在等待的任務。當notifyAll()因某個特定所而被調用時,只有等待這個鎖的任務才會被喚醒,注意不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。23. 鎖的等級
方法鎖:對象鎖(也叫方法鎖)。同步靜態方法/靜態變量互斥體,由於一個class不論被實例化多少次,其中的靜態方法和靜態變量在內存中都只由一份。所以,一旦一個靜態的方法被申明為synchronized。此類所有的實例化對象在調用此方法,共用同一把鎖,我們稱之為類鎖。一旦一個靜態變量被作為synchronized block的mutex。進入此同步區域時,都要先獲得此靜態變量的對象鎖。 對象鎖:是針對一個對象的,它只在該對象的某個內存位置聲明一個標志位標識該對象是否擁有鎖,所以它只會鎖住當前的對象。一般一個對象鎖是對一個非靜態成員變量進行syncronized修飾,或者對一個非靜態方法進行syncronized修飾。對於對象鎖,不同對象訪問同一個被syncronized修飾的方法的時候不會阻塞住。 類鎖:是鎖住整個類的,當有多個線程來聲明這個類的對象的時候將會被阻塞,直到擁有這個類鎖的對象被銷毀或者主動釋放了類鎖。這個時候在被阻塞住的線程被挑選出一個占有該類鎖,聲明該類的對象。其他線程繼續被阻塞住。 對象鎖是用來控制實例方法之間的同步,類鎖是用來控制靜態方法(或靜態變量互斥體)之間的同步。所謂的類鎖,不過是Class對象的鎖而已。獲取類的Class對象有好幾種,最簡單的就是MyClass.class的方式。24. 寫出生產者消費者模式
wait()和notify()實現:
package com.xqq.生產者與消費者之wait和notify實現;
import java.util.LinkedList;
import java.util.Queue;
/**
* 用於存放生產數據的緩沖區隊列
* @author xqq
*/
public class FlowQueue {
private Queue queue = new LinkedList();
private int maxSize;
public FlowQueue(int maxSize) {
this.maxSize = maxSize;
}
public synchronized void put(T v) throws InterruptedException{
while(queue.size() >= maxSize){
wait();
}
queue.offer(v);
notifyAll();
}
public synchronized T get() throws InterruptedException{
while(queue.isEmpty()){
wait();
}
T returnVal = queue.poll();
notifyAll();
return returnVal;
}
}
package com.xqq.生產者與消費者之wait和notify實現;
import java.util.concurrent.TimeUnit;
public class Consumer implements Runnable{
private int delay;
private FlowQueue- input;
public Consumer(int delay, FlowQueue
- input) {
this.delay = delay;
this.input = input;
}
public void run() {
for(;;){
try {
System.out.println("Consumer " + input.get());
TimeUnit.MILLISECONDS.sleep(delay);
} catch (Exception e) {
return;
}
}
}
}
package com.xqq.生產者與消費者之wait和notify實現;
import java.util.concurrent.TimeUnit;
public class Producer implements Runnable{
private int delay;
private FlowQueue
- output;
public Producer(int delay, FlowQueue
- output) {
this.delay = delay;
this.output = output;
}
public void run() {
for(;;){
try {
Item product = new Item();
System.out.println("Product " + product);
output.put(product);
TimeUnit.MILLISECONDS.sleep(delay);
} catch (Exception e) {
return;
}
}
}
}
package com.xqq.生產者與消費者之wait和notify實現;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ProducerConsumer {
public static void main(String[] args) throws InterruptedException {
int producerSleep = 1;
int consumerSleep = 200;
FlowQueue
- fq = new FlowQueue
- (10);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Producer(producerSleep, fq));
exec.execute(new Consumer(consumerSleep, fq));
TimeUnit.SECONDS.sleep(2);
exec.shutdownNow();
}
}
運行結果:
Product Item 0
Consumer Item 0
Product Item 1
Product Item 2
Product Item 3
Product Item 4
Product Item 5
Product Item 6
Product Item 7
Product Item 8
Product Item 9
Product Item 10
Product Item 11
Consumer Item 1
Product Item 12
Consumer Item 2
Product Item 13
Consumer Item 3
Product Item 14
Consumer Item 4
Product Item 15
Consumer Item 5
Product Item 16
Consumer Item 6
Product Item 17
Consumer Item 7
Product Item 18
Consumer Item 8
Product Item 19
Consumer Item 9
Product Item 20
BlockingQueue實現:
package com.xqq.生產者與消費者BlockingQueue實現;
import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable {
private BlockingQueue sharedQueue;
public Consumer(BlockingQueue sharedQueue) {
this.sharedQueue = sharedQueue;
}
public void run() {
for (;;) {
try {
System.out.println("Consumer " + sharedQueue.take());
} catch (Exception e) {
return;
}
}
}
}
package com.xqq.生產者與消費者BlockingQueue實現;
import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable{
private BlockingQueue sharedQueue;
public Producer(BlockingQueue sharedQueue) {
this.sharedQueue = sharedQueue;
}
public void run() {
for(int i = 0; i<10; i++){
try {
System.out.println("Produce " + i);
sharedQueue.put(i);
} catch (Exception e) {
return ;
}
}
}
}
package com.xqq.生產者與消費者BlockingQueue實現;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class ProducerConsumerPattern {
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
BlockingQueue sharedQueue = new LinkedBlockingQueue();
exec.execute(new Producer(sharedQueue));
exec.execute(new Consumer(sharedQueue));
TimeUnit.SECONDS.sleep(3);
exec.shutdownNow();
}
}
運行結果:
Produce 0
Produce 1
Produce 2
Produce 3
Produce 4
Produce 5
Produce 6
Produce 7
Produce 8
Produce 9
Consumer 0
Consumer 1
Consumer 2
Consumer 3
Consumer 4
Consumer 5
Consumer 6
Consumer 7
Consumer 8
Consumer 9
25. ThreadPool用法與優勢
優勢:26. ThreadLocal的設計理念與作用
ThreadLocal不是用來解決對象共享訪問問題的,而主要是提供了保持對象的方法和避免參數傳遞的方便的對象訪問方式。
每個線程中都有一個自己的ThreadLocalMap類對象,可以將線程自己的對象保持到其中,各管各的,線程可以正確的訪問到自己的對象。 將一個ThreadLocal靜態實例作為key,將不同對象的引用保存到不同線程的ThreadLocalMap中,然後在線程執行的各處通過這個靜態ThreadLocal實例的get()方法取得自己線程保存的那個對象,避免了將這個對象作為參數傳遞的麻煩。 ThreadLocal的應用場合,我覺得最適合的是多線程多實例(每個線程對應一個實例)的對象的訪問,並且這個對象很多地方都要用到。27. Concurrent包裡的其它東西
28. wait()和sleep()的區別
這兩個方法來自不同的類分別是,sleep來自Thread類,和wait來自Object類 sleep是Thread的靜態類方法,誰調用的誰去睡覺,即使在a線程裡調用b的sleep方法,實際上還是a去睡覺,要讓b線程睡覺要在b的代碼中調用sleep。 鎖: 最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其他線程可以使用同步控制塊或者方法。最近穿戴設備發展得很火,把相關技術也帶旺了,其中一項是BLE(Bluetooth Low Energy)。BLE是藍牙4.0的核心Profile,主打功能是快速搜索,快速
Context在開發Android應用的過程中扮演著非常重要的角色,比如啟動一個Activity需要使用context.startActivity方法,將一個xml文件轉
本次實例是將用戶的設置信息,以實體類為媒介,保存到內部存儲或者SD卡的文件裡。再次打開應用時,程序會自動調用文件中實體類,並對設置信息進行設置,使其恢復到用戶最終保存的狀
優步(UBER)-全球即時用車軟件,現已覆蓋全球68個國家,444個城市。Uber旨在為大家帶來更安全、更舒適的出行方式,為了保證雙方的安全和隱私,優步(U