一、synchronized與信號量Semaphore簡介
1、synchronized是java中的關鍵字,是用來控制線程同步的問題最常用的方法。
2、Semaphore是屬於java的一個類,同樣是用來控制多個線程同步問題。
二、兩者用法比較
使用synchronized控制多線程的話,同時只有一個線程去訪問資源。就是消費者與生產者兩個線程同時只有其中一個處理產品。
Semaphore可以實現synchronized的功能與synchronized不能實現的功能。假如消費者和生產者線程都有3個,並且能同時運行,使用synchronized控制的話,同時只能有一個線程運行,而Semaphore能夠滿足多個消費者或生產者同時進行消費或生產,能夠控制同時在運行的線程和其數量,提高效率和性能。
三、代碼比較
1、synchronized實現生產者消費者問題
package Synchronized; import java.util.LinkedList; public class ProducerAndConsumer { private static final int size=1;//產品最大的數量 private LinkedList<String> product;//存放產品的鏈表 private Producer producer; private Consumer consumer; public ProducerAndConsumer() { product=new LinkedList<String>(); producer=new Producer(); consumer=new Consumer(); //線程開始 new Thread(producer).start(); new Thread(consumer).start(); } public static void main(String[] args) { ProducerAndConsumer pac=new ProducerAndConsumer(); } class Producer implements Runnable{ @Override public void run() { while(true) { synchronized (product) { try { if (product.size()==size) {//產品數量達到最大時等待 product.wait(); } System.out.println("生產者正在生產。。。"); Product p=new Product((int)(Math.random()*1000000));//產品的隨機 Thread.sleep(1000);//假設生產產品的時間 product.add("產品"+p.geti()); System.out.println("產品"+p.geti()+"生產完成"); product.notify();//釋放鎖 } catch (InterruptedException e) { e.printStackTrace(); } } } } } class Consumer implements Runnable{ @Override public void run() { while(true) { synchronized (product) { try { if (product.isEmpty()) {//產品數量為0時等待 product.wait(); } System.out.println("消費者正在消費。。。"); Thread.sleep(1000); String p=product.remove(); System.out.println(p+"消費完成"); product.notify(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } class Product{//產品類 int i; public Product(int i) { this.i=i; } public int geti() { return i; } } }
2、Semaphore實現消費者生產者問題
package Semaphore; import java.util.LinkedList; import java.util.concurrent.Semaphore; public class ProducerAndConsumer { private static final int size=10;//產品池存放最大數量 private Semaphore empty;//產品池中空的數量,生產者請求empty,消費者釋放empty private Semaphore mutex;//控制只有一個線程進入產品池對產品操作 private Semaphore full;//產品池中滿的數量,生產者釋放full,消費者請求empty private LinkedList<String> product;//存放產品的鏈表,即產品池 private Producer producer; private Consumer consumer; public ProducerAndConsumer() { empty=new Semaphore(size);//初始為最大數量size mutex=new Semaphore(1);//初始為1 full=new Semaphore(0);//初始為0 product=new LinkedList<String>(); producer=new Producer(); consumer=new Consumer(); new Thread(producer).start(); new Thread(consumer).start(); } public static void main(String[] args) { ProducerAndConsumer pac=new ProducerAndConsumer(); } class Producer implements Runnable { @Override public void run() { do { try { empty.acquire();//請求empty信號量 mutex.acquire();//請求mutex信號量 System.out.println("生產者正在生產。。。"); Thread.sleep(1000); Product p=new Product((int)(Math.random()*1000000)); product.add("產品"+p.geti()); System.out.println("產品"+p.geti()+"生產完成"); mutex.release(1);//釋放mutex信號量 full.release(1);//釋放full信號量 } catch (InterruptedException e) { e.printStackTrace(); } } while (true); } } class Consumer implements Runnable { @Override public void run() { do { try { full.acquire();//請求full信號量 mutex.acquire();//請求mutex信號量 System.out.println("消費者正在消費。。。"); Thread.sleep(1000); String s=product.remove(); System.out.println(s+"消費完成"); mutex.release(1);//釋放mutex信號量 empty.release(1);//釋放empty信號量 } catch (InterruptedException e) { e.printStackTrace(); } } while (true); } } class Product { int i; public Product(int i) { this.i=i; } public int geti() { return i; } } }
3、Semaphore實現多個生產者和消費者同時運行的問題
假設產品池最大數量為10,同時運行的線程數最多為2
package Semaphore; import java.util.LinkedList; import java.util.concurrent.Semaphore; public class ProducerAndConsumer { private static final int size=10;//產品池存放最大數量 private Semaphore empty;//產品池中空的數量,生產者請求empty,消費者釋放empty private Semaphore mutex;//控制只有一個線程進入產品池對產品操作 private Semaphore full;//產品池中滿的數量,生產者釋放full,消費者請求empty private LinkedList<String> product;//存放產品的鏈表,即產品池 private Producer producer; private Consumer consumer; public ProducerAndConsumer() { empty=new Semaphore(size);//初始為最大數量size mutex=new Semaphore(2);//修改此處控制同時運行的線程數量 full=new Semaphore(0);//初始為0 product=new LinkedList<String>(); producer=new Producer(); consumer=new Consumer(); //有4個線程請求共同操作共享資源 new Thread(producer).start(); new Thread(consumer).start(); new Thread(producer).start(); new Thread(consumer).start(); } public static void main(String[] args) { ProducerAndConsumer pac=new ProducerAndConsumer(); } class Producer implements Runnable { @Override public void run() { do { try { empty.acquire();//請求empty信號量 mutex.acquire();//請求mutex信號量 System.out.println("生產者"+Thread.currentThread().getName()+"正在生產。。。"); Thread.sleep(1000); Product p=new Product((int)(Math.random()*1000000)); product.add("產品"+p.geti()); System.out.println("產品"+p.geti()+"生產完成"); mutex.release(1);//釋放mutex信號量 full.release(1);//釋放full信號量 } catch (InterruptedException e) { e.printStackTrace(); } } while (true); } } class Consumer implements Runnable { @Override public void run() { do { try { full.acquire();//請求full信號量 mutex.acquire();//請求mutex信號量 System.out.println("消費者"+Thread.currentThread().getName()+"正在消費。。。"); Thread.sleep(1000); String s=product.remove(); System.out.println(s+"消費完成"); mutex.release(1);//釋放mutex信號量 empty.release(1);//釋放empty信號量 } catch (InterruptedException e) { e.printStackTrace(); } } while (true); } } class Product { int i; public Product(int i) { this.i=i; } public int geti() { return i; } } }
三、Semaphore用法簡介
1、初始化信號量
1 Semaphore(permits)//初始化許可證數量的構造函數 2 Semaphore(permits,fair)//初始化許可證數量和是否公平模式的構造函數
2、請求信號量
1 acquire()//當前線程嘗試去阻塞的獲取1個許可證。 2 acquire(permits)//當前線程嘗試去阻塞的獲取permits個許可證
3、釋放信號量
1 release()//當前線程釋放1個可用的許可證。 2 release(permits)//當前線程釋放permits個可用的許可證。
相關鏈接:https://blog.csdn.net/hanchao5272/article/details/79780045
https://www.cnblogs.com/XHJT/p/3910406.html
四、總結
結合自己的學習過程,寫下了自己如何學習多線程的經典問題,還有很多的問題沒有弄清楚,希望能夠繼續加油!!!(我要一步一步往上爬,等待陽光看着它的臉,小小的天有大大的夢想,重重的殼裹着輕輕的仰望----------周傑倫《蝸牛》)
轉載注明出處:https://www.cnblogs.com/chenglin520/p/JayCL.html
