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();

       }

   }

}
相关文章
相关标签/搜索