java使用synchronized與Semaphore解決生產者消費者問題對比


一、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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM