欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java如何實現(xiàn)多個線程之間共享數(shù)據(jù)

 更新時間:2021年11月12日 14:43:53   作者:JUN_LLLL  
這篇文章主要介紹了Java如何實現(xiàn)多個線程之間共享數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

實現(xiàn)多個線程之間共享數(shù)據(jù)

一、 如果每個線程執(zhí)行的代碼相同

可以使用同一個Runnable對象,這個Runnable對象中有那個共享數(shù)據(jù),例如:賣票系統(tǒng)

class Ticket implements Runnable{  
    private  int tick = 20;  
    Object obj = new Object();    
    public void run(){  
        while(true){  
            synchronized(obj){  
                if(tick>0){  
                    //只能try,因為run是復寫了Runnable接口的run,接口的run沒有拋  
                    try{Thread.sleep(100);}catch(Exception e){}  //使用sleep不然執(zhí)行每個線程都會占用完畢
                    System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);  
                }  
            }  
        }  
    }  
}  
  
class  TicketDemo  
{  
    public static void main(String[] args) {  
          
        //只建立了一個Ticket對象,內(nèi)存中只有一個tick成員變量,所以是共享數(shù)據(jù)  
        Ticket t = new Ticket();  
  
        Thread t1 = new Thread(t);  
        Thread t2 = new Thread(t);  
        Thread t3 = new Thread(t);  
        Thread t4 = new Thread(t);  
        t1.start();  
        t2.start();  
        t3.start();  
        t4.start();  
    }  
} 

輸出結果

Thread-0....sale : 20
Thread-1....sale : 19
 .......
Thread-3....sale : 2
Thread-3....sale : 1

二、 如果每個線程執(zhí)行的代碼不同

1、具體實現(xiàn)

將共享數(shù)據(jù)封裝在另外一個對象中,然后將這個對象逐一傳遞給各個Runnable對象。每個線程對共享數(shù)據(jù)的操作方法也分配到那個對象身上去完成,這樣容易實現(xiàn)針對該數(shù)據(jù)進行的各個操作的互斥和通信。

思想: 一個類提供數(shù)據(jù)和操作數(shù)據(jù)的同步方法,另外定義兩個線程通過構造函數(shù)接收并操作數(shù)據(jù),在主函數(shù)中直接創(chuàng)建線程對象,即可完成操作(可以實現(xiàn)兩個內(nèi)部類,不用構造方法傳值,使用final定義data局部變量)

例如: 設計4個線程,其中兩個線程每次對j增加1,另外兩個線程每次對j減少1

public class MultyThreadShareMethod1 {        
    public static void main(String[] args){        
        //將數(shù)據(jù)封裝到一個對象上,  
        ShareData2 data1 = new ShareData2();  
          
        //在runnable的構造函數(shù)中直接傳入去操作  
        for(int i=0;i<2;i++){  
        new Thread(new MyRunnable1(data1)).start();  
        new Thread(new MyRunnable2(data1)).start();  
        }  
    }  
}  
 
//封裝共享數(shù)據(jù)和操作共享數(shù)據(jù)方法的類  
class ShareData2{  
    private int j = 10;  
    public synchronized void increment() {  
        j++;  
        System.out.println(Thread.currentThread().getName()+" inc : "+j);  
    }  
    public synchronized void decrement() {  
        j--;  
        System.out.println(Thread.currentThread().getName()+" dec : "+j);  
    }  
}  
   
//增加的線程,需要傳入一個共享數(shù)據(jù)  
class MyRunnable1 implements Runnable {       
    private ShareData2 data;  
    public MyRunnable1(ShareData2 data) {  
        this.data = data;  
    }  
    @Override  
    public void run() {  
        for(int i=0;i<10;i++){  
        data.increment();  
        }  
    }  
}  
  
//減少的線程,需要傳入一個共享數(shù)據(jù)  
class MyRunnable2 implements Runnable {   
    private ShareData2 data;  
    public MyRunnable2(ShareData2 data) {  
        this.data = data;  
    }  
    @Override  
    public void run() {  
        for(int i=0;i<10;i++){  
        data.decrement();  
        }  
    }  
}  

輸出結果

Thread-0 inc : 11
...
Thread-1 dec : 10

2、 技巧總結

要同步互斥的幾段代碼最好是分別放在幾個獨立的方法中,這些方法再放在同一個類中,這樣比較容易實現(xiàn)它們之間的同步互斥或通信。

極端且簡單的方式,即在任意一個類中定義一個static的變量,這將被所有線程共享。

多線程之間共享數(shù)據(jù)的方式探討

方式一:代碼一致

如果每個線程執(zhí)行的代碼相同,可以用一個 Runnable 對象,這個 Runnable 對象中存放那個共享數(shù)據(jù)(賣票系統(tǒng)可以這樣做)。

public class MultiThreadShareData {
    public static void main(String[] args) {
        MyShareData shareData=new MyShareData();
        //放入不同的線程中
        new Thread(shareData).start(); 
        new Thread(shareData).start(); 
    }
}
 
class MyShareData implements Runnable {
        // 共享的數(shù)據(jù)
        private int count = 100; 
        @Override
        public void run() {
            while (count > 0) {
                synchronized (this) {
                    if (count > 0) {
                        count--;
                        System.out.println(Thread.currentThread().getName() + " 減了1,count還剩:" + count);
                    } 
                } 
            }
        }
    }

方式二:代碼不一致

如果每個線程執(zhí)行的代碼不同時,就需要不同的 Runnable 對象:

a. 將共享數(shù)據(jù)封裝在一個對象中,然后將這個對象逐一傳遞給各個 Runnable 對象,每個線程對共享數(shù)據(jù)操作的方法也分配到這個對象中,這樣容易實現(xiàn)針對該數(shù)據(jù)進行的各個操作的互斥通信。

public class MultiThreadShareData { 
    private int shareData=0; 
    public static void main(String[] args) {
        ShareData data = new ShareData(); 
        new Thread(new MyRunnable1(data)).start(); 
        new Thread(new MyRunnable2(data)).start();
    } 
}
 
class MyRunnable1 implements Runnable{ 
    private ShareData data; 
    public MyRunnable1(ShareData data){
        this.data=data;
    }
 
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            //對數(shù)據(jù)進行增加
            this.data.increment();
        }
    }
}
 
class MyRunnable2 implements Runnable{ 
    private ShareData data; 
    public MyRunnable2(ShareData data){
        this.data=data;
    }
 
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            //對數(shù)據(jù)進行減少
            this.data.decrement();
        }
    }
}
 
/**
 將共享的數(shù)據(jù)封裝成一個類
*/
class ShareData{
    //共享數(shù)據(jù)
    private int j=0; 
    public synchronized void increment(){
        this.j++;
        System.out.println(Thread.currentThread().getName()+":j增加了1后j="+j);
    }
 
    public synchronized void decrement() {
        this.j--;
        System.out.println(Thread.currentThread().getName()+":j減少了1后j="+j);
    }
    public int getJ() {
        return j;
    }
}

b. 將 Runnable 對象作為某一個類的內(nèi)部類,共享數(shù)據(jù)作為這個外部類的成員變量,每個線程對共享數(shù)據(jù)的操作方法也分配到外部類中,實現(xiàn)共享數(shù)據(jù)的互斥和通信操作,作為內(nèi)部類的各個 Runnable 對象調(diào)用外部類的這些方法。

public class MultiThreadShareData { 
    private int shareData=0; 
    public static void main(String[] args) {
        MultiThreadShareData m=new MultiThreadShareData();
        //初始化Runnable對象
        MyRunnable1 myRunnable1 = m.new MyRunnable1();
        MyRunnable2 myRunnable2=m.new MyRunnable2(); 
        //開啟線程
        new Thread(myRunnable1).start(); 
        new Thread(myRunnable2).start();
    }
 
    private synchronized void increment(){
        this.shareData++;
        System.out.println(Thread.currentThread().getName()+":shareData增加了1后shareData="+shareData);
    }
 
    private synchronized void decrement() {
        this.shareData--;
        System.out.println(Thread.currentThread().getName()+":shareData減少了1后shareData="+shareData);
    }
 
    /**
     * 作為內(nèi)部類的Runnable對象
     */
    class MyRunnable1 implements Runnable{ 
        @Override
        public void run() {
            for(int i=0;i<100;i++){
                increment();
            }
        }
    }
 
    class MyRunnable2 implements Runnable{ 
        @Override
        public void run() {
            for(int i=0;i<100;i++){
                decrement();
            }
        }
    }
}

c. 以上兩種方法的組合:將共享數(shù)據(jù)封裝到一個對象中,每個線程對共享數(shù)據(jù)的操作方法也分配到對象中,對象作為外部類的成員變量或方法中的局部變量,每個線程的 Runnable 作為成員內(nèi)部類或局部內(nèi)部類。

 public class MultiThreadShareData {
   public static void main(String[] args) { 
       ShareData data = new ShareData(); 
       new Thread(()->{
           for(int i=0;i<100;i++){
               data.increment();
           }
       }).start();
 
       new Thread(()->{
           for (int j=0;j<100;j++) {
               data.decrement();
           }
       }).start();
   } 
}
 
/**
封裝共享數(shù)據(jù)的對象
*/
class ShareData{
   //共享數(shù)據(jù)
   private int j=0;
 
   /**
    對共享數(shù)據(jù)進行操作的方法
   */
   public synchronized void increment(){
       this.j++;
       System.out.println(Thread.currentThread().getName()+":j增加了1后j="+j);
   }
 
   public synchronized void decrement() {
       this.j--;
       System.out.println(Thread.currentThread().getName()+":j減少了1后j="+j);
   }
 
   public int getJ() {
       return j;
   }
}

總之,要同步互斥的幾段代碼最好放在幾個獨立的方法中,這些方法再放入一個類中,這樣比較容易實現(xiàn)它們之間的同步互斥和通信。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java拋出異常與自定義異常類應用示例

    Java拋出異常與自定義異常類應用示例

    這篇文章主要介紹了Java拋出異常與自定義異常類,結合實例形式分析了Java針對錯誤與異常處理的try、catch、throw等語句相關使用技巧,需要的朋友可以參考下
    2019-03-03
  • Java簡單工廠模式詳細解釋

    Java簡單工廠模式詳細解釋

    本文主要介紹了JAVA簡單工廠模式(從現(xiàn)實生活角度理解代碼原理)的相關知識。具有很好的參考價值。下面跟著小編一起來看下吧
    2021-11-11
  • Spring如何消除代碼中的if-else/switch-case

    Spring如何消除代碼中的if-else/switch-case

    這篇文章主要給大家介紹了關于Spring如何消除代碼中if-else/switch-case的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-04-04
  • Spring+SpringMVC配置事務管理無效原因及解決辦法詳解

    Spring+SpringMVC配置事務管理無效原因及解決辦法詳解

    這篇文章主要介紹了Spring+SpringMVC配置事務管理無效原因及解決辦法詳解,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • SSH框架網(wǎng)上商城項目第7戰(zhàn)之整合Struts2和Json

    SSH框架網(wǎng)上商城項目第7戰(zhàn)之整合Struts2和Json

    SSH框架網(wǎng)上商城項目第7戰(zhàn)之整合Struts2和Json,打通EasyUI和Struts2之間的交互,感興趣的小伙伴們可以參考一下
    2016-05-05
  • SPRING BOOT啟動命令參數(shù)及源碼詳析

    SPRING BOOT啟動命令參數(shù)及源碼詳析

    這篇文章主要給大家介紹了關于SPRING BOOT啟動命令參數(shù)及源碼分析的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用SPRING BOOT具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-12-12
  • java中的類為什么只能用public修飾?

    java中的類為什么只能用public修飾?

    這篇文章主要介紹了java中的類為什么只能用public修飾,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • mybatis中使用not?in與?in的寫法說明

    mybatis中使用not?in與?in的寫法說明

    這篇文章主要介紹了mybatis中使用not?in與?in的寫法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java中Stream流去除List重復元素的方法

    Java中Stream流去除List重復元素的方法

    這篇文章主要為大家詳細介紹了Java中Stream流去除List重復元素的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • springboot+mybatis-plus實現(xiàn)內(nèi)置的CRUD使用詳解

    springboot+mybatis-plus實現(xiàn)內(nèi)置的CRUD使用詳解

    這篇文章主要介紹了springboot+mybatis-plus實現(xiàn)內(nèi)置的CRUD使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12

最新評論