JUC 線程問題

1 賣票

package net.nlpeng;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadTicket {

    public static void main(String[] args) {
        final Ticket ticket = new Ticket();
        new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i=0;i<50;i++){

                    ticket.sale();
                }

            }
        }, "AA").start();
        new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i=0;i<50;i++){
                    ticket.sale();
                }

            }
        }, "BB").start();
        new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i=0;i<50;i++){
                    ticket.sale();
                }

            }
        }, "CC").start();
        new Thread(new Runnable() {

            @Override
            public void run() {
                for(int i=0;i<50;i++){
                    ticket.sale();
                }

            }
        }, "DD").start();
    }
    /**
     * 資源類
     */
    static class Ticket {
        private int tickte = 40;

        public void sale() {

            Lock lock = new ReentrantLock();
            if (tickte > 0) {
                lock.lock();
                try {
                    tickte--;
                    System.out.println("線程" + Thread.currentThread().getName() + "餘票:" + tickte);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }

            }
        }
    }

}

 

2 四種建立線程的方式

1 繼承Thread類

package net.nlpeng;

publicclass Thread8Lock {

   publicstaticvoid main(String[] args) {

      new Thread(new TestThread()).start();   

   }

}

class TestThread extends Thread{

   @Override

   publicvoid run() {

      //biz...

      super.run();

   }

}

 

 

2 實現Runnable接口

package net.nlpeng;



publicclass Thread8Lock {

   publicstaticvoid main(String[] args) {

      new Thread(new TestThread()).start();   

   }

}



class TestThread implements Runnable{

   @Override

   publicvoid run() {

      //biz...

   }

}

 

3 實現Callable接口

package net.nlpeng;



import java.util.Random;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.FutureTask;



public class ThreadCallable {

  

   public static void main(String[] args) throws InterruptedException, ExecutionException {

       FutureTask<Integer> futureTask = new FutureTask<Integer>(new TestCallable());

       new Thread(futureTask).start();

       System.out.println(futureTask.get());

   }  

}



class TestCallable implements Callable<Integer>{



   @Override

   public Integer call() throws Exception {

      

       System.out.println("come in call....");

      

       return new Random().nextInt(10);

   }  

}

 

4 從ThreadPool中取得

 

 

3 線程同步的方式

1 synchronized關鍵字

1 同步方法

publicsynchronizedvoid sale(){}java

2 同步代碼塊

Synchronized(this){}dom

2 Lock類

publicvoid sale() {


      Lock lock = new ReentrantLock();

      if (tickte> 0) {

          lock.lock();

          try {

             tickte--;

             System.out.println("線程" + Thread.currentThread().getName() + "餘票:" + tickte);

          } catch (Exception e) {

             e.printStackTrace();

          } finally {

             lock.unlock();

          }


      }

   }

 

4 線程通訊(生產者和消費者模式)

1 . 4個線程,實現對初始值爲0的number,兩個加操做,兩個減操做

package net.nlpeng;



import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;



public class LockConditionThread {

   public static void main(String[] args) {

       final Share share = new Share();

      

       new Thread(new Runnable(){



          @Override

          public void run() {

              for(int i=0;i<20;i++){

                 share.increment();

              }

          }

         

       },"AA+").start();

       new Thread(new Runnable(){



          @Override

          public void run() {

              for(int i=0;i<20;i++){

                 share.decrement();

              }

             

          }

         

       },"BB-").start();

       new Thread(new Runnable(){



          @Override

          public void run() {

              for(int i=0;i<20;i++){

                 share.increment();

              }         

          }

         

       },"CC+").start();

       new Thread(new Runnable(){



          @Override

          public void run() {

              for(int i=0;i<20;i++){

                 share.decrement();

              }            

          }

         

       },"DD-").start();

   }

  

}

class Share{

   private int number=0;

   Lock lock = new ReentrantLock();

   Condition condition = lock.newCondition();

   public void increment(){

                    

   try{

       lock.lock();

       while(number !=0){//避免線程的虛假喚醒

          condition.await();

       }

      

       ++number;

       System.out.println(Thread.currentThread().getName()+"number:"+number);

       condition.signalAll();

   }catch(InterruptedException e){

       e.printStackTrace();

   }finally{

       lock.unlock();

   }     

   }

  

   public void decrement(){

      

       lock.lock();

       try{

         

          while(number ==0){

              condition.await();

          }

         

          --number;

           System.out.println(Thread.currentThread().getName()+"number:"+number);

          condition.signalAll();

         

       }catch(InterruptedException e){

          e.printStackTrace();

       }finally{

          lock.unlock();

       }

      

      

   }

}

2 兩個線程,打印結果爲: 12A34B56C……

package net.nlpeng;



import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;



class ShareSource {

   private Lock lock = new ReentrantLock();

   private Condition c1 = lock.newCondition();

   private int i = 1;

   private int num=0;

   public void printNum() {

  

       lock.lock();

       try {

          while ( num % 2 != 0) {

              c1.await();

          }

          System.out.print(i++);

          System.out.print(i++);

          num++;

          c1.signal();

         

       } catch (Exception e) {

          e.printStackTrace();

       } finally {

          lock.unlock();

       }

   }



   public void printChar(int j) {

       lock.lock();

       try {

          while (num % 2 == 0) {

              c1.await();

          }

          char c = (char) ('A' + j);

          System.out.print(c);

          num++;

          c1.signal();



       } catch (Exception e) {

          e.printStackTrace();

       } finally {

          lock.unlock();

       }

   }

}



public class ThreadCommu {

   public static void main(String[] args) throws InterruptedException {

       final ShareSource share = new ShareSource();

       new Thread(new Runnable() {



          @Override

          public void run() {

              for (int i = 0; i <26; i++) {

                 share.printNum();

              }

          }

       }).start();

      

       Thread.sleep(200);



       new Thread(new Runnable() {

          @Override

          public void run() {

              for (int i = 0; i <26; i++) {

                 share.printChar(i);

              }

          }

       }).start();

   }

}

 

5 線程八鎖

 

class Phone{

   publicsynchronizedvoid getIOS(){



      System.out.println("--------IOS");

   }

   publicsynchronizedvoid getAndroid(){

      System.out.println("--------Android");

   }

   publicvoid getHello(){

      System.out.println("-------Hello");

   }

}



publicclass Thread8Lock {

   publicstaticvoid main(String[] args) {

     

      final Phone phone = new Phone();

      new Thread(new Runnable(){

          @Override

          publicvoid run() {

            

             phone.getIOS();

          } 

      },"AA").start();

      new Thread(new Runnable(){

          @Override

          publicvoid run() {

             phone.getAndroid();

          } 

      },"BB").start();

   }

}

 

1 兩個線程標準訪問普通的同步方法,先打印IOS仍是Android

2新增Thread.sleep(4000),先打印IOS仍是Android

publicstaticsynchronizedvoid getIOS(){

      try {

          Thread.sleep(4000);

      } catch (InterruptedException e) {

          e.printStackTrace();

      }

      System.out.println("--------IOS");

   }

3 新增getHello方法,先打印IOS仍是Hello

final Phone phone = new Phone();

      new Thread(new Runnable(){

          @Override

          publicvoid run() {

             phone.getIOS();

          } 

      },"AA").start();

      new Thread(new Runnable(){

          @Override

          publicvoid run() {

             phone.getHello();

          } 

      },"BB").start();

   }

4有兩部手機,先打印先打印IOS仍是Android

publicstaticvoidmain(String[] args) {

     

      final Phone phone = new Phone();

      final Phone phone2=new Phone();

      new Thread(new Runnable(){

          @Override

          publicvoid run() {

             phone.getIOS();

          } 

      },"AA").start();

      new Thread(new Runnable(){

          @Override

          publicvoid run() {

             phone2.getAndroid();

          } 

      },"BB").start();

   }

5 兩個靜態同步方法,同一部手機,先打印IOS仍是Android

6兩個靜態同步方法,兩部手機,先打印IOS仍是Android

7 一個靜態同步方法,一個普通同步方法,一部手機,先打印IOS仍是Android

8 一個靜態同步方法,一個普通同步方法,兩部手機,先打印IOS仍是Android

結論:

•        一個對象裏面若是有多個synchronized方法,某一個時刻內,只要一個線程去調用其中的一個synchronized方法了,其它的線程都只能等待,換句話說,某一個時刻內,只能有惟一一個線程去訪問這些synchronized方法ide

•        鎖的是當前對象this,被鎖定後,其它的線程都不能進入到當前對象的其它的synchronized方法oop

•        加個普通方法後發現和同步鎖無關this

•        換成兩個對象後,不是同一把鎖了,狀況馬上變化。spa

•        都換成靜態同步方法後,狀況又變化線程

•        全部的非靜態同步方法用的都是同一把鎖——實例對象自己,也就是說若是一個實例對象的非靜態同步方法獲取鎖後,該實例對象的其餘非靜態同步方法必須等待獲取鎖的方法釋放鎖後才能獲取鎖,但是別的實例對象的非靜態同步方法由於跟該實例對象的非靜態同步方法用的是不一樣的鎖,因此毋須等待該實例對象已獲取鎖的非靜態同步方法釋放鎖就能夠獲取他們本身的鎖。
全部的靜態同步方法用的也是同一把鎖——類對象自己,這兩把鎖是兩個不一樣的對象,因此靜態同步方法與非靜態同步方法之間是不會有競態條件的。可是一旦一個靜態同步方法獲取鎖後,其餘的靜態同步方法都必須等待該方法釋放鎖後才能獲取鎖,而無論是同一個實例對象的靜態同步方法之間,仍是不一樣的實例對象的靜態同步方法之間,只要它們同一個類的實例對象!code

 

6 通知喚醒按序(線程接力)

三個線程,AA打印5次,BB打印10次,CC打印15次,共計來20輪

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;



class ShareResource {

   private int flag = 1;// AA:1;BB:2;CC:3

   private Lock lock = new ReentrantLock();

   private Condition c1 = lock.newCondition();

   private Condition c2 = lock.newCondition();

   private Condition c3 = lock.newCondition();



   public void LoopAA(int num) {

       lock.lock();

       try {

          while (flag != 1) {

              c1.await();

          }

          for (int i = 1; i <= 5; i++) {

              System.out.println(Thread.currentThread().getName() + "--" + i + "---------" + num);

          }

          flag = 2;

          c2.signal();

       } catch (Exception e) {

          e.printStackTrace();



       } finally {

          lock.unlock();

       }

   }



   public void LoopBB(int num){

       lock.lock();

       try {

          while (flag != 2) {

              c2.await();

          }

          for (int i = 1; i <= 10; i++) {

              System.out.println(Thread.currentThread().getName() + "--" + i + "---------" + num);

          }

          flag = 3;

          c3.signal();

       } catch (Exception e) {

          e.printStackTrace();



       } finally {

          lock.unlock();

       }

   }



   public void LoopCC(int num){

       lock.lock();

       try {

          while (flag != 3) {

              c3.await();

          }

          for (int i = 1; i <= 15; i++) {

              System.out.println(Thread.currentThread().getName() + "--" + i + "---------" + num);

          }

          flag = 1;

          c1.signal();

       } catch (Exception e) {

          e.printStackTrace();

       } finally {

          lock.unlock();

       }

   }

}



public class ThreadOrder {

   public static void main(String[] args) {

       final ShareResource share = new ShareResource();

       new Thread(new Runnable() {

          @Override

          public void run() {

              for (int i = 1; i <= 20; i++) {

                     share.LoopAA(i);

              }

          }

       }, "AA").start();

       new Thread(new Runnable() {

          @Override

          public void run() {

              for (int i = 1; i <= 20; i++) {          

                     share.LoopBB(i);        

              }

          }

       }, "BB").start();

       new Thread(new Runnable() {

          @Override

          public void run() {

              for (int i = 1; i <= 20; i++) {

                     share.LoopCC(i);

                     System.out.println();

              }

          }

       }, "CC").start();

   }

}

7 讀寫鎖

一個線程寫,100個讀

import java.util.Random;

importjava.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantReadWriteLock;



class Queue {

   private Object obj;

   private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();



   publicvoid read() {

      lock.readLock().lock();

      try {

          System.out.println(Thread.currentThread().getName() + "---------" + obj);

      } catch (Exception e) {

          e.printStackTrace();

      } finally {

          lock.readLock().unlock();

      }

   }



   publicvoid write(Object obj) {

      lock.writeLock().lock();

      try {

          this.obj = obj;

          System.out.println(Thread.currentThread().getName() + "---------" + obj);

      } catch (Exception e) {

          e.printStackTrace();

      } finally {

          lock.writeLock().unlock();

      }

   }

}



publicclass ReadWriteDemo {



   publicstaticvoid main(String[] args) throws InterruptedException {

      final Queue queue = new Queue();

      new Thread(new Runnable() {



          @Override

          publicvoid run() {

             queue.write(new Random().nextInt(100));

          }

      }, "wiriteLock").start();

      Thread.sleep(200);

      for(inti=1;i<=100;i++){

          new Thread(new Runnable() {



             @Override

             publicvoid run() {

                queue.read();

             }

          }, "readLock"+i).start();



         

      }

     

   }



}

 

8 線程池

 

1三種方式配置線程池

import java.util.Random;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;



publicclass ThreadPool {

  

   publicstaticvoid main(String[] args) {

      //初始有五個線程的線程池

   // ExecutorService service = Executors.newFixedThreadPool(5);

      //初始只有一個線程的線程池

      //ExecutorService service=Executors.newSingleThreadExecutor();

      //自適應的線程數,須要幾個就建立幾個

      ExecutorService service=Executors.newCachedThreadPool();

      Future<Integer>result=null;

     

      try {

          for(inti=0;i<1000;i++){

          result = service.submit(new Callable<Integer>() {

             @Override

             public Integer call() throws Exception {

                System.out.print(Thread.currentThread().getName());

                returnnew Random().nextInt(50);

             }

          });

          System.out.println("--------------"+result.get());

          }

         

      } catch (Exception e) {

      }finally{

          service.shutdown();

      }

   }

}

2 時間調度線程池

import java.util.Random;

import java.util.concurrent.Callable;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;



public class ThreadSchedulePool {



   public static void main(String[] args) {

       ScheduledExecutorService service = Executors.newScheduledThreadPool(5);

       Future<Integer> result = null;

       try {

          for (int i = 1; i <=20; i++) {

          result =   service.schedule(new Callable<Integer>() {



                 @Override

                 public Integer call() throws Exception {

                     System.out.print(Thread.currentThread().getName());

                     return new Random().nextInt(50);

                 }

              }, 3,TimeUnit.SECONDS);//三秒調度一次

         

          System.out.println("--------"+result.get());

             

          }

       } catch (Exception e) {

       } finally {

          service.shutdown();

       }

   }

}
相關文章
相關標籤/搜索