Java多線程、併發

Java裏面在處理任務,好比和用戶交互的過程當中,不可避免的要用到多線程一遍監聽用戶輸入,一遍處理任務,這時就涉及到併發了。關於併發狀況要考慮的不少,這裏只是簡單記錄一下。
1、線程:
1.在java中線程分爲普通線程和守護線程(也叫後臺線程),普通線程裏面開啓的線程默認爲普通線程,守護線程裏面開啓的線程默認爲守護線程。固然普通線程也能夠設置是否爲守護線程:java

Thread thread=new Thread(runnable);
       //設置是否爲守護線程
		thread.setDaemon(true);

當普通線程都結束時,後臺線程也會忽然都關閉終止,由於此時jvm會關閉全部的後臺進程。
2.在Android裏面主要分爲主線程和子線程。打開APP默認的任務都運行在主線程中,本身開的線程就是子線程。子線程不能更新UI,只能在主線程中更新。
線程能夠在run方法的開頭,設置線程優先級:程序員

public void run() {
		Thread.currentThread().setPriority(priority);	
	}

不過它只是一個建議,不能保證必定優先級高的先執行,因此在處理多線程時,用這個不太靠譜。
2、多線程:
在開線程處理任務時,Thread thread=new Thread(r);就開了一個線程,當有大量併發任務,要開不少線程時,怎麼處理控制比較好呢?JDK提供了ExecutorService來處理:編程

//建立線程池,默認線程數爲0,當有任務須要執行時,會先查看是否有空閒的可用線程,沒有就建立新的線程
		ExecutorService cachedExecutorService = Executors.newCachedThreadPool();
		//建立線程池,默認線程數爲3,固定只有3個線程,多餘的任務排隊執行
		ExecutorService fixedExecutorService = Executors.newFixedThreadPool(3);
		//建立線程池,只有一個線程,任務排隊一個一個執行,Executors.newFixedThreadPool(1)同樣
		ExecutorService singleExecutorService = Executors.newSingleThreadExecutor();
		//使用線程池代替直接new線程去執行Runnable任務
		fixedExecutorService.execute(new Runnable() {
			
			@Override
			public void run() {
				//要執行的任務
			}
		});

3、併發:
多線程的執行時機是不肯定的,以單核CPU爲例,在執行多線程時是CPU在分時間片切換執行線程,致使好像是多線程併發執行。若是是多核多是真正在併發執行,不過這不是重點,重點是:若是一個線程在操做打印機打印東西到一半,這時切換到另外一個線程也在操做這個打印機打印東西,這個時候打印出來的東西就亂套了。怎麼處理這種狀況呢?JDK提供了
1.synchronized關鍵字,就是給上一把鎖,當這個方法被調用時加上一把鎖,等方法執行完返回時釋放鎖。方法執行期間,其它線程來執行該方法時,只能在方法外面等候。多線程

public synchronized void status(){
       //同一時間,只能有一個線程執行此方法
		try {
			TimeUnit.MILLISECONDS.sleep(sleepTime);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(name);
		
	}

這個鎖默認是這個對象自己,也可使用synchronized 代碼塊本身換鎖:併發

synchronized (new String("lock")) {
			 //......
		}

2.使用volatile 關鍵字來定義變量,能夠得到原子性和可視性,也能夠用來作同步處理。jvm

volatile int data ;

不過這樣作是有風險的,首選仍是synchronized.
3.使用JDK提供的鎖Lock:ide

public void doSomething(){
		Lock lock=new ReentrantLock();
		lock.lock();
		//可能出現多線程同時執行的任務...
		lock.unlock();
	}

4.使用同步隊列BlockingQueue,把須要執行的任務runnable都裝進去,在執行的時候會依次一個個取出來執行。
5.有些容器是自帶鎖,有些是免鎖容器沒有鎖。當在非多線程程序中使用自帶鎖容器時,會致使很大的開銷。
不一樣的方式,在不一樣的環境下性能也不同,最終結果仍是取決於本身的測試。
4、死鎖:
多線程併發,採起同步處理後,可能會引起另外一個問題:死鎖。經典問題是哲學家就餐問題
同時知足如下4個條件時,死鎖就會產生:
1.任務使用的資源中是不能共享的 。
2.一個任務持有一個資源,同時在等待另外一個任務持有的資源。
3.資源不能被任務搶奪,是任務本身釋放的。
4.循環等待,即任務1在等待任務2,任務2在等待任務3...任務N-1在等待任務N,任務N在等待任務1。
編程時真正的問題在於,程序看起來在正確運行,但可能潛在死鎖的危險。這就要靠程序員本身來判斷避免死鎖了,good luck。性能

相關文章
相關標籤/搜索