Java高级编程-JUC

来源:互联网 发布:intent传递数据 编辑:程序博客网 时间:2024/06/17 06:35

1.Volatile关键字

package cn.zzu.wcj.juc;/** *  * @author WangChengJian * volatile关键字:当多个线程进行操作共享数据时,可以保证内存中的数据的可见性 *               相较于synchronized关键字是一种较为轻量级的同步策略 * 注意: *   1.volatile不具备互斥性 *   2.volatile不能保证变量的原子性              * */public class TestVolatile {    public static void main(String[] args) {        ThreadDemo td=new ThreadDemo()   ;        new Thread(td).start();           while(true){            if(td.isFlag()){                System.out.println("--------------");                break   ;            }        }    }}class ThreadDemo implements Runnable{    private volatile boolean flag=false   ;    public boolean isFlag() {        return flag;    }    public void setFlag(boolean flag) {        this.flag = flag;    }    @Override    public void run() {            try {                Thread.sleep(2000) ;            } catch (InterruptedException e) {                e.printStackTrace();            }            this.flag=true   ;            System.out.println("flag="+this.isFlag());    }}

2.原子变量

package cn.zzu.wcj.juc;import java.util.concurrent.atomic.AtomicInteger;/* * 一、i++ 的原子性问题:i++ 的操作实际上分为三个步骤“读-改-写” *        int i = 10; *        i = i++; //10 *  *        int temp = i; *        i = i + 1; *        i = temp; *  * 二、原子变量:在 java.util.concurrent.atomic 包下提供了一些原子变量。 *      1. volatile 保证内存可见性 *      2. CAS(Compare-And-Swap) 算法保证数据变量的原子性 *          CAS 算法是硬件对于并发操作的支持 *          CAS 包含了三个操作数: *          ①内存值  V *          ②预估值  A *          ③更新值  B *          当且仅当 V == A 时, V = B; 否则,不会执行任何操作。 */public class TestAtomicDemo {   public static void main(String[] args) {       AtomicDemo ad=new AtomicDemo()   ;       for(int i=0;i<10;i++){           new Thread(ad).start();          }  }}class AtomicDemo implements Runnable{    //private volatile int serialNumber= 0 ;    private AtomicInteger serialNumber=new AtomicInteger()   ;    @Override    public void run() {          try {            Thread.sleep(200);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(this.getSerialNumber());    }    public int getSerialNumber() {        return serialNumber.getAndIncrement();    }}

3.闭锁

package cn.zzu.wcj.juc;import java.util.concurrent.CountDownLatch;/* * CountDownLatch :闭锁,在完成某些运算时,只有其他所有线程的运算全部完成,当前运算才继续执行 */public class TestCountDownLatch {   public static void main(String[] args) throws Exception {      final CountDownLatch latch=new CountDownLatch(10)   ;      LatchDemo ld=new LatchDemo(latch)   ;      long start=System.currentTimeMillis()    ;      for(int i=0;i<10;i++){          new Thread(ld).start();      }      latch.await();      long end=System.currentTimeMillis()    ;      System.out.println("耗时:"+(end-start));   }}class LatchDemo implements Runnable {    private CountDownLatch latch   ;    public LatchDemo(CountDownLatch latch){        this.latch=latch   ;    }    @Override    public void run() {        synchronized (this) {                 try{                     for (int i = 0; i < 6000; i++) {                        if(i%2==0){                            System.out.println(i);                        }                    }                   }finally{                    latch.countDown();                   }           }    }}

4.线程的第三种创建方式

package cn.zzu.wcj.juc;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;/* * 一、创建执行线程的方式三:实现 Callable 接口。 相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。 *  * 二、执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。  FutureTask 是  Future 接口的实现类 */public class TestCallable {   public static void main(String[] args)throws Exception {       CallThread ct=new CallThread()   ;       //1.执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。       FutureTask<Integer> result = new FutureTask<Integer>(ct);       new Thread(result).start();          //2.接收线程运算后的结果      Integer sum=result.get()  ; //FutureTask 可用于 闭锁      System.out.println("sum="+sum);      System.out.println("-----------------------------");   } }class CallThread implements Callable<Integer>{    @Override    public Integer call() throws Exception {        Integer sum=0   ;        for (int i = 0; i < 10; i++) {            System.out.println(i);            sum=sum+i   ;        }        return sum;    }}

5.线程锁

package cn.zzu.wcj.juc;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/* * 一、用于解决多线程安全问题的方式: *  * synchronized:隐式锁 * 1. 同步代码块 *  * 2. 同步方法 *  * jdk 1.5 后: * 3. 同步锁 Lock * 注意:是一个显示锁,需要通过 lock() 方法上锁,必须通过 unlock() 方法进行释放锁 */public class TestLock {     public static void main(String[] args) {        Ticket ticket=new Ticket()   ;        new Thread(ticket,"窗口1").start();        new Thread(ticket,"窗口2").start();        new Thread(ticket,"窗口3").start();    }}class Ticket implements Runnable{    private Integer ticket = 10 ;    private Lock lock=new ReentrantLock()  ;    @Override    public void run() {        while(true){            lock.lock(); //上锁            try{                if(this.ticket > 0){                    try {                        Thread.sleep(200);                    } catch (InterruptedException e) {                    }                    System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --this.ticket);                }            }finally{                lock.unlock(); //释放锁            }        }    }}

6.线程八锁

package cn.zzu.wcj.juc;/* * 题目:判断打印的 "one" or "two" ? *  * 1. 两个普通同步方法,两个线程,标准打印, 打印? //one  two * 2. 新增 Thread.sleep() 给 getOne() ,打印? //one  two * 3. 新增普通方法 getThree() , 打印? //three  one   two * 4. 两个普通同步方法,两个 Number 对象,打印?  //two  one * 5. 修改 getOne() 为静态同步方法,打印?  //two   one * 6. 修改两个方法均为静态同步方法,一个 Number 对象?  //one   two * 7. 一个静态同步方法,一个非静态同步方法,两个 Number 对象?  //two  one * 8. 两个静态同步方法,两个 Number 对象?   //one  two *  * 线程八锁的关键: * ①非静态方法的锁默认为  this,  静态方法的锁为 对应的 Class 实例 * ②某一个时刻内,只能有一个线程持有锁,无论几个方法。 */public class TestThread8Monitor {      public static void main(String[] args) {          final Number number=new Number()   ;          final Number number2=new Number()   ;          new Thread(new Runnable() {                            @Override                            public void run() {                                number.getOne();                            }                     }).start();          new Thread(new Runnable() {                            @Override                            public void run() {                                number2.getTwo();                            }                    }).start();//        new Thread(new Runnable() {//                        @Override//                        public void run() {//                            number.getTree();//                        }//                  }).start();    }}class Number{    public static  synchronized void getOne(){        try{            Thread.sleep(2000);        }catch(Exception e){}        System.out.println("one");    }    public static  synchronized void getTwo(){        System.out.println("two");    }    public void getTree(){        System.out.println("three");    }}

7.读写锁

package cn.zzu.wcj.juc;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;/* * 1. ReadWriteLock : 读写锁 *  * 写写/读写 需要“互斥” * 读读 不需要互斥 *  */public class TestReadWriteLock {   public static void main(String[] args) {       final ReadWriteLockDemo rw=new ReadWriteLockDemo()  ;       for(int i=0;i<10;i++){           final int  x=i+1 ;           new Thread(new Runnable() {                @Override                public void run() {                    rw.set(x);                }         },"写线程"+i).start();        }       for(int j=0;j<10;j++){           new Thread(new Runnable() {                            @Override                            public void run() {                                rw.get();                            }                       },"读线程-"+j).start();       }    }}class ReadWriteLockDemo{    private Integer num=0   ;    private ReadWriteLock lock=new ReentrantReadWriteLock()  ;  //读写锁    public void get(){        this.lock.readLock().lock();           try{             System.out.println(Thread.currentThread().getName()+"-->num:"+num);        }finally{             this.lock.readLock().unlock();          }    }    public void set(Integer num){         this.lock.writeLock().lock();          try{             this.num=num   ;             System.out.println(Thread.currentThread().getName()+"-->num:"+num);         }finally{             this.lock.writeLock().unlock();         }    }}

8.线程池

package cn.zzu.wcj.juc;import java.util.ArrayList;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/* * 一、线程池:提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提高了响应的速度。 *  * 二、线程池的体系结构: *  java.util.concurrent.Executor : 负责线程的使用与调度的根接口 *      |--**ExecutorService 子接口: 线程池的主要接口 *          |--ThreadPoolExecutor 线程池的实现类 *          |--ScheduledExecutorService 子接口:负责线程的调度 *              |--ScheduledThreadPoolExecutor :继承 ThreadPoolExecutor, 实现 ScheduledExecutorService *  * 三、工具类 : Executors  * ExecutorService newFixedThreadPool() : 创建固定大小的线程池 * ExecutorService newCachedThreadPool() : 缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量。 * ExecutorService newSingleThreadExecutor() : 创建单个线程池。线程池中只有一个线程 *  * ScheduledExecutorService newScheduledThreadPool() : 创建固定大小的线程,可以延迟或定时的执行任务。 */public class TestThreadPool {  public static void main(String[] args)throws Exception {      //1.创建线程池      ExecutorService pool = Executors.newFixedThreadPool(8) ;      //2.为线程池中的线程分配任务      //TaskThread task=new TaskThread()   ;      //pool.submit(task)  ;      List<Future<Integer>> results=new ArrayList<Future<Integer>>()   ;      for(int i=0;i<10;i++){          Future<Integer> result = pool.submit(new Callable<Integer>() {                                                    @Override                                                    public Integer call() throws Exception {                                                        int sum=0  ;                                                        for(int j=0;j<=10;j++){                                                            sum=sum+j   ;                                                        }                                                        return sum;                                                    }                                                 })  ;          results.add(result)  ;      }      for(Future<Integer> result : results){          System.out.println(result.get());      }      //3.关闭线程池      pool.shutdown();    }}class TaskThread implements Runnable{    private Integer num= 0 ;    @Override    public void run() {        while(this.num<=100){            System.out.println(Thread.currentThread().getName()+" : num="+(this.num++));        }    }}
package cn.zzu.wcj.juc;import java.util.Random;import java.util.concurrent.Callable;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;/* * 一、线程池:提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提高了响应的速度。 *  * 二、线程池的体系结构: *  java.util.concurrent.Executor : 负责线程的使用与调度的根接口 *      |--**ExecutorService 子接口: 线程池的主要接口 *          |--ThreadPoolExecutor 线程池的实现类 *          |--ScheduledExecutorService 子接口:负责线程的调度 *              |--ScheduledThreadPoolExecutor :继承 ThreadPoolExecutor, 实现 ScheduledExecutorService *  * 三、工具类 : Executors  * ExecutorService newFixedThreadPool() : 创建固定大小的线程池 * ExecutorService newCachedThreadPool() : 缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量。 * ExecutorService newSingleThreadExecutor() : 创建单个线程池。线程池中只有一个线程 *  * ScheduledExecutorService newScheduledThreadPool() : 创建固定大小的线程,可以延迟或定时的执行任务。 */public class TestScheduledThreadPool {    public static void main(String[] args) {        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(6)  ;        for(int x=0;x<8;x++){                    threadPool.schedule(new Callable<Integer>() {                                                @Override                                                public Integer call() throws Exception {                                                    Integer result=new Random().nextInt(100)  ;                                                    System.out.println(Thread.currentThread().getName()+" : result="+result);                                                    return result  ;                                                 }                                          }, 1, TimeUnit.SECONDS)  ;        }        threadPool.shutdown();      }}

9.生产者消费者问题

package cn.zzu.wcj.juc;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class TestProductAndConsumerForLock {   public static void main(String[] args) {       Clerk clerk=new Clerk()    ;       Product pro=new Product(clerk)  ;       Consumer cons=new Consumer(clerk)  ;       new Thread(pro,"生产者A").start();       new Thread(cons,"消费者B").start();       new Thread(pro,"生产者C").start();       new Thread(cons,"消费者D").start();   }}class Clerk{    private int product=0  ;    private Lock lock=new ReentrantLock()   ;    private Condition condition=this.lock.newCondition()  ;    //进货    public  void  get() throws Exception{        this.lock.lock();        try{            while(this.product>=1){                System.out.println("产品已满!");                this.condition.await();            }            System.out.println(Thread.currentThread().getName()+":"+(++this.product));            this.condition.signalAll();        }finally{            this.lock.unlock();          }    }    //卖货    public  void sale()throws Exception{          this.lock.lock();          try{              while(this.product<=0){                  System.out.println("缺货!");                  this.condition.await();              }              System.out.println(Thread.currentThread().getName()+":"+(--this.product));              this.condition.signalAll();          }finally{              this.lock.unlock();          }    }}//生产者class Product implements Runnable{    private Clerk clerk    ;    public Product(Clerk clerk){        this.clerk=clerk   ;    }    @Override    public void run() {         for (int i = 0; i < 20; i++) {            try{                Thread.sleep(200);                this.clerk.get();            }catch(Exception e){}        }    }}//消费者class Consumer implements Runnable{    private Clerk clerk    ;    public Consumer(Clerk clerk){          this.clerk=clerk    ;    }    @Override    public void run() {         for(int i=0;i<20;i++){                 try {                    this.clerk.sale();                } catch (Exception e) {}         }    }}

10.线程通信

package cn.zzu.wcj.juc;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/* * 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。 *  如:ABCABCABC…… 依次递归 */public class TestABCAlternate {   public static void main(String[] args) {       final AlternateDemo ad=new AlternateDemo()   ;       new Thread(new Runnable() {                            @Override                            public void run() {                                for(int i=0;i<10;i++){                                    try {                                        ad.loopA();                                    } catch (Exception e) {                                          e.printStackTrace();                                    }                                }                            }    },"A").start();    new Thread(new Runnable() {            @Override            public void run() {                for(int i=0;i<10;i++){                    try {                        ad.loopB();;                    } catch (Exception e) {                          e.printStackTrace();                    }                }            }     },"B").start();    new Thread(new Runnable() {        @Override        public void run() {            for(int i=0;i<10;i++){                try {                    ad.loopC();                } catch (Exception e) {                      e.printStackTrace();                }            }        }     },"C").start();   }}class AlternateDemo{      private Integer number=1  ;   //当前正在执行的线程的标记      private Lock lock=new ReentrantLock()   ;      private Condition conditionA=lock.newCondition()  ;      private Condition conditionB=lock.newCondition()  ;      private Condition conditionC=lock.newCondition()  ;      public void loopA()throws Exception{          this.lock.lock();             try{              if(this.number != 1){                  this.conditionA.await();              }              for(int i=0;i<1;i++){                  System.out.print("A");              }              this.number=2   ;              conditionB.signal();              }finally{              this.lock.unlock();            }      }      public void loopB()throws Exception{          this.lock.lock();             try{              if(this.number != 2){                  this.conditionB.await();              }              for(int i=0;i<1;i++){                  System.out.print("B");              }              this.number=3   ;              conditionC.signal();              }finally{              this.lock.unlock();            }      }      public void loopC()throws Exception{          this.lock.lock();             try{              if(this.number != 3){                  this.conditionC.await();              }              for(int i=0;i<1;i++){                  System.out.print("C");              }              this.number=1   ;              conditionA.signal();              }finally{              this.lock.unlock();            }      }}

11.ForkJoin框架

package cn.zzu.wcj.juc;import java.util.concurrent.ForkJoinPool;import java.util.concurrent.ForkJoinTask;import java.util.concurrent.RecursiveTask;public class TestForkJoinPool {   public static void main(String[] args) {      Long start=System.currentTimeMillis()   ;      ForkJoinPool pool=new ForkJoinPool()   ;      ForkJoinTask<Long> task=new ForkJoinSumCalculate(0L,50000000L)  ;      Long sum=pool.invoke(task)  ;      System.out.println(sum);      Long end=System.currentTimeMillis()   ;      System.out.println("框架执行耗时:"+(end-start)+"毫秒");   }}class ForkJoinSumCalculate extends RecursiveTask<Long>{    private static final long serialVersionUID = 1L;    private long start      ;    private long end        ;    private static final long THURSHOLD=10000L  ;    public ForkJoinSumCalculate(long start,long end){          this.start=start  ;          this.end=end   ;    }    @Override    protected Long compute() {        long length=end-start   ;        if(length <= THURSHOLD){            long sum=0L   ;            for(long x=start;x<=end;x++){                 sum+=x   ;            }            return sum   ;        }else{            long middle=(start+end)/2   ;            ForkJoinSumCalculate left=new ForkJoinSumCalculate(start,middle)   ;            left.fork()  ;   //进行拆分,同时压入线程队列            ForkJoinSumCalculate right=new ForkJoinSumCalculate(middle+1,end)   ;               right.fork()   ;            return left.join()+right.join();        }    }}

12.线程容器

package cn.zzu.wcj.juc;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;/* * CopyOnWriteArrayList/CopyOnWriteArraySet : “写入并复制” * 注意:添加操作多时,效率低,因为每次添加时都会进行复制,开销非常的大。并发迭代操作多时可以选择。 */public class TestCopyOnWriteArrayList {   public static void main(String[] args) {       HelloThread ht=new HelloThread()    ;       for(int i=0;i<10;i++){            new Thread(ht).start();       }   }}class HelloThread implements Runnable{    //private static List<String> list=Collections.synchronizedList(new ArrayList<String>());    private static CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>();    static {        list.add("AA")  ;        list.add("BB")  ;        list.add("CC")  ;    }    @Override    public void run() {            Iterator<String> it=list.iterator()   ;            while(it.hasNext()){                System.out.println(it.next());                list.add("DD")  ;            }    }}
0 0
原创粉丝点击