多线程及线程并发库

1. 创建和启动线程的两种传统方式

概念:java 实现一条线索
有两种方法:
1、继承thread 类
例子:
// 继承Thread类

 new Thread(){
        publicvoid run(){
          while(true){
             try {
                Thread.sleep(2000);
             }catch (InterruptedException e) {
                e.printStackTrace();
             }
   System.out.println(Thread.currentThread().getName());
          }
        }
      }.start();  

2、实现runnable接口
例子:

//实现Runnable接口
      new Thread(new Runnable(){
        publicvoid run(){
          while(true){
             try {
                Thread.sleep(2000);
             }catch (InterruptedException e) {
                e.printStackTrace();
             }
          System.out.println(Thread.currentThread().getName());
          }
        }
      }).start();

2.传统的定时器实现方式
代码

importjava.util.concurrent.Executors;
importjava.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
publicclass TimerTest {
   /**
    * 定时器
    */
   publicstaticvoid main(String[] args) {
      ScheduledExecutorServiceservice =  Executors.newScheduledThreadPool(3);
      service.scheduleAtFixedRate(
          new Runnable(){
             publicvoid run() {
                System.out.println(Thread.currentThread().getName());
             }

          },
          10,
          1,
          TimeUnit.SECONDS);

      while(true){
        try {
          Thread.sleep(2000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName());
      }
   }

}

3.传统的线程同步互斥

 线程的同步和互斥
   Synchronized
线程创建过程:同步:子线程循环10次,接着主线程循环100次,接着的又回到子线程循环10次,接着又回到主线程循环10次。如此,循环50次。
packageorg.nagi.Thread;
publicclass TeaTSynchronized {
   static Businessbusiness =new Business();
   publicstaticvoid main(String[] args)throws InterruptedException {
      //子线程
      TeaTSynchronized.init();
      //主线程
      for(int i=0;i<50;i++){
        business.main();
      }
   }

   //子线程
   publicstaticvoid init(){
        new Thread(new Runnable() {
          @Override
          publicvoid run() {
             for(int i=0;i<50;i++){
                 try {
                   business.sub();
                }catch (InterruptedException e) {
                   e.printStackTrace();
                }
             }
          }
        }).start();
   }
}
 class Business{
    booleanshouldSub =true;

    //子线程方法
    publicsynchronizedvoid sub()throws InterruptedException{
      //使用我当前线程的,等待
       while(!shouldSub){//这里使用while而不用iF防止假唤醒!详细信息可参考JavaApi
         this.wait();
            }
       for(int i=0;i<10;i++){
         System.out.println(Thread.currentThread().getName()+"count" + i);
       }
       shouldSub = false;
       this.notify();

    }
    //主线程的操作方法
    publicsynchronizedvoid main()throws InterruptedException{
       while(shouldSub){//这里使用while而不用iF防止假唤醒!详细信息可参考JavaApi
         //使用我当前线程的,等待
         this.wait();
       }
       for(int i=0;i<100;i++){
         System.out.println(Thread.currentThread().getName()+"count" + i);
       }
       shouldSub = true;
       this.notify();
    }
}

4.传统的线程间通讯

 ThreadLoacal 线程间的通信:就是线程内的数据共享,两个或多个代码块共享的一个数据, 在代码块之间数据是独立,在代码块之内是数据共享的。

5.ThreadLocal与线程级变量共享

   ThreadLoacal就相当Map; 一个线程TheadLoacal 只能放一个数据;

6.多线程访问共享数据的经典总结

   1、可以把需要共享的数据转给runnable 接口;
   2、将共享数据的封装为一个对象, 在多个线程里面runnable 接口run方法
   3、可以使用ThreadLocal类

如果想要操作一个原子性的数据类型可以用原子方式更新的 int 值。
在操作某一个数据原子性操作的时候,可以使用AtomicInteger AtomicIntegerArray

 定义一个线程池:
packageorg.nagi.Thread;

importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;

/**
 *线程池
 *@author dell
 *
 */
publicclass ThreadPool {
   publicstaticvoid main(String[] args) {
      /*缓存线程池*/
      //ExecutorService  threadcached=Executors.newCachedThreadPool();
      /*单个线程池,当线程死了,自动会有线程启动*/
      //ExecutorService threadSingle = Executors.newSingleThreadScheduledExecutor();
      //线程池
      ExecutorService  threadPool = Executors.newFixedThreadPool(4);
        threadPool.execute(new Runnable() {
          @Override
          publicvoid run() {
             for(int i=0;i<5;i++){
                System.out.println(Thread.currentThread().getName()+"任务:"+ i);
             }
          }
        });
        //当任务执行完成之后就可以关闭掉
        threadPool.shutdown();
   }
}

8.Java5中的定时器

方法参考
ScheduledFuture
schedule(Callable callable, long delay, TimeUnit unit)
创建并执行在给定延迟后启用的 ScheduledFuture。
ScheduledFuture

   Executors.newScheduledThreadPool(4).scheduleAtFixedRate(
             new Runnable() {
                @Override
                publicvoid run() {
                   System.out.println("Bombing");
                }
             },
             4,//多少秒之后执行run方法
             2,//间隔多少时间执行
              TimeUnit.SECONDS);//时间单位
Callable和Futrue使用:

        /*使用Callable调用回返一个数据,使用futrue去取并且可以指定时间*/
        ExecutorService  threadSingle = Executors.newSingleThreadExecutor();
        Future<String> futrue =threadSingle.submit(newCallable<String>() {

          @Override
          public String call()throws Exception {
             Thread.sleep(1000);
             return"hello world";
          }
        });
        try {
          //futrue取出数据
          System.out.println("result:" + futrue.get(3,TimeUnit.SECONDS));
        } catch (Exceptione) {
          e.printStackTrace();
        }

9.java5提供的可返回结果的线程模式

10.java5中的锁与读写锁

Lock:java 中锁Lock 比Synchronized更加的面对对象,与生活中的对象一样,锁业是一个对象。
例子代码:

importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;

publicclass LockTest {

   /**
    * @param args
    */
   publicstaticvoid main(String[] args) {
      final Business business =new Business();
      ExecutorService service = Executors.newFixedThreadPool(3);
      for(int i=0;i<3;i++){
        service.execute(new Runnable(){
          publicvoid run(){
             business.service();
          }
        });
      }
      service.shutdown();
   }
}
class Business{
   privateintcount = 0;
   Lock lock = new ReentrantLock();
   publicvoid service(){
      lock.lock();
      count++;
      try {
        Thread.sleep(10);
        System.out.println(count);    
      } catch (InterruptedException e) {
        e.printStackTrace();
      }finally{
        lock.unlock();
      }

   }
}

Lock : 还可以实现一个读写锁,
/**
    * 读的的时候不互斥
    * 写的时候互斥
    * @param key
    * @return
    */
   public Object getEntityFromCache(Stringkey){

      Object object = cache.get(key);
      if(object ==null){
        lock.readLock().lock();//锁得read操作
        try{
          object ="btbu";//去数据库查找
          cache.put(key, object);
        }finally{
          lock.readLock().unlock();
        }
      }
      return object;
   }

11.LockCondition同步工具

Condition 将 Object 监视器方法(wait、notify和notifyAll)分解成截然不同的对象,以便通过将这些对象与任意Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

例子:

packageorg.nagi.Thread;

import java.util.concurrent.locks.Condition;
importjava.util.concurrent.locks.ReentrantLock;


publicclass TestCondition {
   static Businessbusiness =new Business();
   publicstaticvoid main(String[] args)throws InterruptedException {
      //子线程
      TestCondition.init();
      //主线程
      for(int i=0;i<50;i++){
        business.main();
      }
   }

   //子线程
   publicstaticvoid init(){
        new Thread(new Runnable() {
          @Override
          publicvoid run() {
             for(int i=0;i<50;i++){
                 try {
                   business.sub();
                }catch (InterruptedException e) {
                   e.printStackTrace();
                }
             }
          }
        }).start();

   }

}
 class Business{
    booleanshouldSub =true;

    ReentrantLock lock = new ReentrantLock();
    Condition condition =lock.newCondition();

    //子线程方法
    public void sub()throws InterruptedException{
       lock.lock();
       try{
          //使用我当前线程的,等待
           while(!shouldSub){//这里使用while而不用iF防止假唤醒!详细信息可参考JavaApi
               condition.await();
                }
           for(int i=0;i<10;i++){
              System.out.println(Thread.currentThread().getName()+"count" + i);
           }
           shouldSub =false;
       }finally{
         condition.signal();
       }

    }
    //主线程的操作方法
    publicsynchronizedvoid main()throws InterruptedException{
       lock.lock();
       try{
         while(shouldSub){//这里使用while而不用iF防止假唤醒!详细信息可参考JavaApi
           //使用我当前线程的,等待
           condition.await();
         }
         for(int i=0;i<100;i++){
           System.out.println(Thread.currentThread().getName()+"count" + i);
         }
         shouldSub = true;
         this.notify();
       }finally{
         condition.signal();
       }
    }
}

缓冲队列的实现

import java.util.concurrent.locks.Condition;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
/**
 *缓冲队列
 *@author dell
 *
 */
class BoundedBuffer{
   final Locklock =new ReentrantLock();
   final ConditionnotFull =lock.newCondition();
   final ConditionnotEmpty =lock.newCondition();

   //一个数组的缓存区
   final Object[]items =new Object[100];
   intputptr,takeptr,count;

   //存放的操作
   publicvoid put(Object x)throws InterruptedException {
     lock.lock();
     try {
       while (count ==items.length)
         notFull.await();
       items[putptr] = x;
       if (++putptr ==items.length)putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   //取出数据的操作
   public Object take()throwsInterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr];
       if (++takeptr ==items.length)takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
 }

12.Semaphore同步工具

代码:

importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importjava.util.concurrent.Semaphore;

/**
 *信号灯
 *@author dell
 *
 */
publicclass SemaphoreTest {
   publicstaticvoid main(String[] args) {
      //缓存连接池
      ExecutorService service = Executors.newCachedThreadPool();
      final Semaphore sp =new Semaphore(3);
      for(int i=0;i<10;i++){
        Runnable runnable = new Runnable(){
             publicvoid run(){
             try {
                sp.acquire();//获得信号量许可
             }catch (InterruptedException e1) {
                e1.printStackTrace();
             }
             System.out.println("线程" + Thread.currentThread().getName() +
                   "进入,当前已有" + (3-sp.availablePermits()) +"个并发");
             try {
                Thread.sleep((long)(Math.random()*10000));
             }catch (InterruptedException e) {
                e.printStackTrace();
             }
             System.out.println("线程" + Thread.currentThread().getName() +
                   "即将离开");             
              sp.release();//释放信号量
             //下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
             System.out.println("线程" + Thread.currentThread().getName() +
                   "已离开,当前已有" + (3-sp.availablePermits()) +"个并发");             
          }
        };
        //执行已提交的 Runnable任务的对象。
        service.execute(runnable);    
      }
   }

}

运行结果:
线程pool-1-thread-1进入,当前已有1个并发
线程pool-1-thread-1即将离开
线程pool-1-thread-1已离开,当前已有0个并发
线程pool-1-thread-2进入,当前已有1个并发
线程pool-1-thread-2即将离开
线程pool-1-thread-2已离开,当前已有0个并发
线程pool-1-thread-3进入,当前已有1个并发
线程pool-1-thread-3即将离开

13.CyclicBarrier同步工具

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环的 barrier。

代码:

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *并发工具辅佐类
 *
 *之循环障碍点
 *@author dell
 *
 */
publicclass CyclicBarrierTest {

   publicstaticvoid main(String[] args) {
      ExecutorService service = Executors.newCachedThreadPool();
      final CyclicBarrier cb =newCyclicBarrier(3);
      for(int i=0;i<3;i++){
        Runnable runnable = new Runnable(){
             publicvoid run(){
             try {
                Thread.sleep((long)(Math.random()*10000));  
               System.out.println("线程" + Thread.currentThread().getName() +
                     "即将到达集合地点1,当前已有" + cb.getNumberWaiting() +"个已经到达,正在等候");               
                cb.await();

                Thread.sleep((long)(Math.random()*10000));  
               System.out.println("线程" + Thread.currentThread().getName() +
                     "即将到达集合地点2,当前已有" + cb.getNumberWaiting() +"个已经到达,正在等候");               
                cb.await();
                Thread.sleep((long)(Math.random()*10000));  
               System.out.println("线程" + Thread.currentThread().getName() +
                     "即将到达集合地点3,当前已有" + cb.getNumberWaiting() +"个已经到达,正在等候");               
                cb.await();             
             }catch (Exception e) {
                e.printStackTrace();
             }         
          }
        };
        service.execute(runnable);

      }
      service.shutdown();
   }

}

14.CountDownLatch同步工具

一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。首先先是点时器,
用给定的计数 初始化 CountDownLatch。由于调用了countDown()方法,所以在当前计数到达零之前,await方法会一直受阻塞。之后,会释放所有等待的线程,await的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。

importjava.util.concurrent.CountDownLatch;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;

/**
 *程序计数器
 *@author dell
 *
 */
publicclass CountdownLatchTest {

   publicstaticvoid main(String[] args) {
      ExecutorService service = Executors.newCachedThreadPool();
      //命令
      final CountDownLatch cdOrder =new CountDownLatch(1);
      //需要3个都为了时候再执行
      final CountDownLatch cdAnswer =new CountDownLatch(3);    
      for(int i=0;i<3;i++){
        Runnable runnable = new Runnable(){
             publicvoid run(){
              try {
               System.out.println("线程" + Thread.currentThread().getName() +
                     "正准备接受命令");               
                cdOrder.await();
               System.out.println("线程" + Thread.currentThread().getName() +
                "已接受命令");                   
                Thread.sleep((long)(Math.random()*10000));  
               System.out.println("线程" + Thread.currentThread().getName() +
                     "回应命令处理结果");
                //减1,当计数器为0的时候,再可以往下执行
                cdAnswer.countDown();              
             }catch (Exception e) {
                e.printStackTrace();
             }         
          }
        };
        service.execute(runnable);
      }    
      try {
        Thread.sleep((long)(Math.random()*10000));

        System.out.println("线程" + Thread.currentThread().getName() +
             "即将发布命令");              
        cdOrder.countDown();
        System.out.println("线程" + Thread.currentThread().getName() +
        "已发送命令,正在等待结果");
        cdAnswer.await();
        System.out.println("线程" + Thread.currentThread().getName() +
        "已收到所有响应结果");
      } catch (Exception e) {
        e.printStackTrace();
      }         
      service.shutdown();
   }
}

15.Exchanger同步与数据交换工具

可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给exchange方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被视为SynchronousQueue 的双向形式。Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用。
importjava.util.concurrent.Exchanger;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;

/**
 *当两个现场都到达的时候,再可以实现线程的数据交换
 *@author dell
 *
 */
publicclass ExchangerTest {

   publicstaticvoid main(String[] args) {
      ExecutorService service = Executors.newCachedThreadPool();
      finalExchanger exchanger =newExchanger();
      service.execute(new Runnable(){
        publicvoid run() {
          try {        
             Thread.sleep((long)(Math.random()*10000));
             String data1 ="zxx";
             System.out.println("线程" + Thread.currentThread().getName() +
             "正在把数据" + data1 +"换出去");
             String data2 = (String)exchanger.exchange(data1);
             System.out.println("线程" + Thread.currentThread().getName() +
             "换回的数据为" + data2);
          }catch(Exception e){

          }
        } 
      });
      service.execute(new Runnable(){
        publicvoid run() {
          try {        
             Thread.sleep((long)(Math.random()*10000));
             String data1 ="lhm";
             System.out.println("线程" + Thread.currentThread().getName() +
             "正在把数据" + data1 +"换出去");
             String data2 = (String)exchanger.exchange(data1);
             System.out.println("线程" + Thread.currentThread().getName() +
             "换回的数据为" + data2);
          }catch(Exception e){

          }         
        } 
      });    
   }
}

16.Java5中的可阻塞队列
队列:先进先出

   import java.util.concurrent.ArrayBlockingQueue;
importjava.util.concurrent.BlockingQueue;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;

/**
 *阻塞队列
 *@author dell
 *
 */
publicclass BlockingQueueCondition {

   publicstaticvoid main(String[] args) {
      ExecutorService service = Executors.newSingleThreadExecutor();
      final Business3 business =new Business3();
      service.execute(new Runnable(){

        publicvoid run() {
          for(int i=0;i<50;i++){
             business.sub();
          }
        }

      });

      for(int i=0;i<50;i++){
        business.main();
      }
   }

}
class Business3{
   //队列
   BlockingQueue subQueue =newArrayBlockingQueue(1);
   BlockingQueue mainQueue =newArrayBlockingQueue(1);
   {//匿名构造方法,有多少个对象就有多少匿名构造方法
      try {
        mainQueue.put(1);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
   }
   publicvoid sub(){
      try
      {
        mainQueue.take();
        for(int i=0;i<10;i++){
          System.out.println(Thread.currentThread().getName()+" :" + i);
        }
        subQueue.put(1);
      }catch(Exception e){

      }
   }

   publicvoid main(){

      try
      {
        subQueue.take();
        for(int i=0;i<5;i++){
          System.out.println(Thread.currentThread().getName()+" :" + i);
        }
        mainQueue.put(1);
      }catch(Exception e){
      }    
   }
}

17.传统与java5中的同步集合

1、在java5 之后并入了一个并发事务库
java.util.concurrent
在并发编程中很常用的实用工具类。

2、HashSet 是单列表的只有的一个Key,而HashMap 双列表一个key 和一个value,HashSet 是底层是使用HashMap ,只是不用Value的那一部分。

3、在迭代集合集合的时候不能对集合进行需要。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值