對多線程的理解(1)

最近摸索了一下多線程,記錄下心得緩存

1.安全

package com.chenzheng.cn.demo.contorller;多線程

/**
 * 演示出線程的緩存問題
 * 1.若是兩個線程同時操做同一個變量
 * 2.則cpu會把這個變量的副本放入緩存中
 * 3.等到cpu運行結束以後,纔會把這個緩存返回出來
 * 4.若是不限制主線程,那麼主線程打印出來的結果就是最開始的數據
 * @author Administrator
 *
 */
public class ThreadCache 
{
    //1.申明一個變量,供其餘線程調用
    private static int a = 0;
    public static void main(String[] args) {
        
        //2.啓動兩個線程,均完成變量+1操做
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("進入線程1時,a的值 = "+a);
                a++;
            }
        });
        
        Thread thread2 = new Thread(new Runnable() {
            
            @Override
            public void run() {
                System.out.println("進入線程2時,a的值 = "+a);
                a++;
            }
        });
        
        thread1.start();
        thread2.start();
        System.out.println("主線程中,a的值="+a);
    }
}
//最後打印出的結果爲:
//進入線程1時,a的值 = 0
//進入線程2時,a的值 = 0
//主線程中,a的值=0
//由此能夠看出,a的數據出現了錯誤ide

 

2.this

package com.chenzheng.cn.demo.contorller;.net

/**
 * 1.爲了讓主線程可以等待子線程運行完以後再來取到具體的值
 * 2.第一個想到的方法就是讓主線程中止一段時間
 * @author Administrator
 *
 */
public class ThreadCache1
{
        //1.申明一個變量,供其餘線程調用
        private static int a = 0;
        public static void main(String[] args) {
            
            //2.啓動兩個線程,均完成變量+1操做
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("進入線程1時,a的值 = "+a);
                    a++;
                    System.out.println("退出線程1是,a的值 = "+a);
                }
            });
            
            Thread thread2 = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    System.out.println("進入線程2時,a的值 = "+a);
                    a++;
                    System.out.println("退出線程2時,a的值 = "+a);
                }
            });
            
            try {
                thread1.start();
                thread2.start();
                Thread.sleep(100);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("主線程中,a的值="+a);
        }
}線程

//進入線程2時,a的值 = 0
//退出線程2時,a的值 = 1
//進入線程1時,a的值 = 0
//退出線程1是,a的值 = 2
//主線程中,a的值=2
//從這裏能夠看出,靜態的共享數據,在進入線程的時候的數據都是0
//而在線程1開始執行新增操做的時候,共享數據已經發生了改變,直接被改變成了2
//最後的返回結果則爲2
//不過這樣處理就會出現另外的問題,咱們不知道線程裏邏輯的複雜程度,若是定了主線程休息100毫秒,
//子線程運行完了或者沒有運行完,都會影響系統的效率或則數據安全
//所以須要一個通知,但願線程在執行完以後可以主動的告訴主線程我完成了任務get

 

 

3.it

package com.chenzheng.cn.demo.contorller;io

public class ThreadCache2 
{
            //1.申明一個變量,供其餘線程調用
            private static int a = 0;
            public static void main(String[] args) {
                
                //2.啓動兩個線程,均完成變量+1操做
                Thread thread1 = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("進入線程1時,a的值 = "+a);
                        a++;
                        System.out.println("退出線程1是,a的值 = "+a);
                    }
                });
                
                Thread thread2 = new Thread(new Runnable() {
                    
                    @Override
                    public void run() {
                        System.out.println("進入線程2時,a的值 = "+a);
                        a++;
                        System.out.println("退出線程2時,a的值 = "+a);
                    }
                });
                
                try {
                    thread1.start();
                    thread2.start();
                    //在這個方法前面的過後,兩個線程都是啓動着的,在這個方法後面經過join方法阻塞了主線程,使得主線程只能等待子線程
                    //完成以後才能接着執行下去
                    thread1.join();
                    thread2.join();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("主線程中,a的值="+a);
            }
}

//這樣就實現了主線程在子線程執行完以後再執行的目的
//若是咱們想要確保子線程之間的關聯關係要怎麼辦呢,就是線程之間的通信


//假設一個場景,,如今線程一是供貨商 suppier , 另一個線程則是收貨放銷售方 customer
//那麼只有供貨商提供了貨物以後,收貨方纔有機會能獲得貨物才能夠售貨出去
 

 

4.

package com.chenzheng.cn.demo.contorller;

public class ThreadCache31 extends Thread
{
    private Object lock;
    
    public ThreadCache31(Object lock) 
    {
        this.lock = lock;
    }
    
    public void run() 
    {
        while(true) 
        {
            synchronized (lock) {
                if(ThreadCache3Test.shoppingList.isEmpty()) 
                {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                else {
                    System.out.println("取出貨物" + ThreadCache3Test.shoppingList.get(0));
                    
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

package com.chenzheng.cn.demo.contorller;

public class ThreadCache32 extends Thread {     private Object lock;          private int index = 0;          public ThreadCache32(Object lock)      {         this.lock = lock;     }          public void run()      {         while(true)          {             synchronized (lock)              {                 ThreadCache3Test.shoppingList.add(index+"");                 System.out.println("放入的貨物爲"+ index);                 index ++ ;                 lock.notifyAll();                 try {                     Thread.sleep(1000);                 } catch (InterruptedException e) {                     // TODO Auto-generated catch block                     e.printStackTrace();                 }             }         }     } }

相關文章
相關標籤/搜索