java线程并发库

 

ThreadLocal的使用,,,实际上相当于维护了一个Map,其中以键值对的形式,存储了某一个数据被多个线程访问所对应的值。当然这个数据只能有一份,可以是List。。可以是对象。。可以是javabean。。。其Map中每一个Entry保存进去的键就是当前线程,值就是这个线程所访问的那份数据。。。。比方说在服务器端单独起一个独立线程来实现与某个客户端交互,,,其中交互过程里所有涉及到的公共模块所访问的都是一份数据,,所以顾名思义被叫做线程范围内的数据共享。。。。。想象的到在javaEE中的应用是非常多的。。。。

 

 

  1. package localTest;  
  2.   
  3. //import java.util.HashMap;   
  4. //import java.util.Map;   
  5. import java.util.Random;  
  6.   
  7. public class ThreadLocalTest {  
  8.     public static int data;  
  9. //  public static Map dataMap = new HashMap();   
  10. //  public static ThreadLocal dataLocal = new ThreadLocal();   
  11.     public static void main(String[] args) {  
  12.         for (int i = 0; i < 2; i++) {  
  13.             new Thread() {  
  14.                 public void run() {  
  15. //                  ThreadLocalTest.data = new Random().nextInt();   
  16. //                  ThreadLocalTest.dataMap.put(Thread.currentThread().getName(),   
  17. //                          new Random().nextInt());   
  18. //                  ThreadLocalTest.dataLocal.set(new Random().nextInt());   
  19.                     int data = new Random().nextInt();  
  20.                     MyData.getInstance().setData(data);  
  21.                     System.out.println(Thread.currentThread().getName()  
  22.                             + " put data : " + data);  
  23.                     System.out.println(Thread.currentThread().getName()  
  24.                             +" A get data : " + new A().get());  
  25.                     System.out.println(Thread.currentThread().getName()  
  26.                             +" B get data : " + new B().get());  
  27.                 }  
  28.             }.start();  
  29.         }  
  30.     }  
  31.   
  32. }  
  33.   
  34. class A {  
  35.     public int get() {  
  36. //      return (Integer)ThreadLocalTest.dataLocal.get();   
  37.         return MyData.getInstance().getData();  
  38.     }  
  39. }  
  40.   
  41. class B {  
  42.     public int get() {  
  43. //      return (Integer)ThreadLocalTest.dataLocal.get();   
  44.         return MyData.getInstance().getData();  
  45.     }  
  46. }  
  47.   
  48. class MyData{  
  49.     private static ThreadLocal<MyData> myData = new ThreadLocal<MyData>();  
  50.     private int data;  
  51.     public int getData(){  
  52.         return data;  
  53.     }  
  54.     public void setData(int data){  
  55.         this.data = data;  
  56.     }  
  57.     private MyData(){}  
  58.     public static MyData getInstance(){  
  59.         MyData data = myData.get();  
  60.         if(data==null){  
  61.             data = new MyData();  
  62.             myData.set(data);  
  63.         }  
  64.         return data;  
  65.     }  
  66. }  

 

接着是线程并发库中的java.util.concurrent.atomic包中提供了对一些数据类型的扩展,使得对那些数据类型的操作封装成为了方法,而那些方法都是线程安全的,atomic解释是原子的,,支持在单个变量上解除锁的线程安全编程。。。。其中包括Integer,boolean以及IntegerArray和引用类型。。

 

 

接下来就是线程池了,,于jdbc数据库连接池同理,,大大的提高了程序运行的效率。。因为创建一个新的线程还是很耗资源的。。

我们也只需要用到一个类,,java.util.concurrent包的老大,,,Executors类,,提供一系列静态方法,用于创建各种线程池,,其中包含固定大小线程,和自动大小线程池(通过任务数量来分配线程数量),以及单一线程池(始终保持有一个线程在池子里)。。。还有可调度的线程池,相当于定时器。。其中定时器任务代码内还可嵌套另外的定时器。。。通过调用线程池的shutdown方法在任务执行完毕后杀死池内线程。shutdownNow直接杀死。。interrupt!ALL!!!

 

  1. package concurrent;  
  2.   
  3. import java.util.Random;  
  4. import java.util.concurrent.ExecutorService;  
  5. import java.util.concurrent.Executors;  
  6.   
  7. public class ThreadPoolTest {  
  8.     public static void main(String[] args) {  
  9.         ExecutorService pool = Executors.newCachedThreadPool();//Executors.newFixedThreadPool(3);   
  10.         for (int i = 0; i < 10; i++) {  
  11.             final int taskId = i;  
  12.             pool.execute(new Runnable() {  
  13.                 public void run() {  
  14.                     for (int j = 0; j < 10; j++) {  
  15.                         try {  
  16.                             Thread.sleep(new Random().nextInt(1000));  
  17.                         } catch (InterruptedException e) {  
  18.                             e.printStackTrace();  
  19.                         }  
  20.                         System.out.println(Thread.currentThread().getName()  
  21.                                 + " execute task " + taskId +   
  22.                                 " loop for " + j);  
  23.                     }  
  24.                 }  
  25.             });  
  26.         }  
  27.         pool.shutdown();  
  28.     }  
  29. }  
  30.   
  31.   
  32.   
  33.   
  34.   
  35. package concurrent;  
  36.   
  37. import java.util.Calendar;  
  38. import java.util.concurrent.Executors;  
  39. import java.util.concurrent.ScheduledExecutorService;  
  40. import java.util.concurrent.TimeUnit;  
  41.   
  42. public class TimerTaskTest {  
  43.     private static int count;  
  44.     public static void main(String[] args) {  
  45.         System.out.println(Calendar.getInstance().get(Calendar.SECOND));  
  46.         final ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);  
  47.         class MyTask implements Runnable{  
  48.             public void run(){  
  49.                 count++;  
  50.                 System.out.println(Calendar.getInstance().get(Calendar.SECOND));  
  51.                 System.out.println("bombing!");  
  52.                 if(count%2==1)  
  53.                     timer.schedule(new MyTask(), 4, TimeUnit.SECONDS);  
  54.                 else  
  55.                     timer.schedule(new MyTask(), 3, TimeUnit.SECONDS);  
  56.             }  
  57.         }  
  58.         timer.schedule(new MyTask(), 2, TimeUnit.SECONDS);  
  59.     }  
  60. }  

 

 

 Callable让线程能够拥有返回值,类似于Runnable接口,,需要实现call方法,,Future类接受一个Callable的返回值。。。通过get方法获取返回值,当没有数据时,它将会等待,什么时候有数据什么时候获取,通过get方法的重载方法可以设置等待时间。。多个Callable利用CompletionService对象来接收返回值,通过submit来接受提交的任务!!!接受返回值时谁先有数据就提取谁的数据!通过take方法放回一个Future对象再调用get方法获取数据。

 

 

  1. package concurrent;  
  2.   
  3. import java.util.concurrent.Callable;  
  4. import java.util.concurrent.CompletionService;  
  5. import java.util.concurrent.Executor;  
  6. import java.util.concurrent.ExecutorCompletionService;  
  7. import java.util.concurrent.ExecutorService;  
  8. import java.util.concurrent.Executors;  
  9. import java.util.concurrent.Future;  
  10. import java.util.concurrent.TimeUnit;  
  11.   
  12. public class CallableTest {  
  13.     public static void main(String[] args) throws Exception {  
  14.         ExecutorService pool = Executors.newSingleThreadExecutor();  
  15.         Future<String> future = pool.submit(new Callable<String>() {  
  16.             @Override  
  17.             public String call() throws Exception {  
  18.                 // TODO Auto-generated method stub   
  19.                 Thread.sleep(3000);  
  20.                 return "Hello world!";  
  21.             }  
  22.         });  
  23.           
  24.         try {  
  25.             System.out.println(future.get(4,TimeUnit.SECONDS));  
  26.         } catch (Exception e) {  
  27.             e.printStackTrace();  
  28.         }  
  29.         pool.shutdown();  
  30.         submit();  
  31.     }  
  32.     public static void submit() throws Exception{  
  33.         Executor executor = Executors.newCachedThreadPool();  
  34.         CompletionService<Integer> service = new ExecutorCompletionService<Integer>(executor);  
  35.         for(int i=0;i<10;i++){  
  36.             final int sep = i;  
  37.             service.submit(new Callable<Integer>() {  
  38.                 public Integer call() throws Exception {  
  39.                     Thread.sleep((int)(Math.random()*1000));  
  40.                     return sep;  
  41.                 }  
  42.             });  
  43.         }  
  44.         for(int i=0;i<10;i++){  
  45.             System.out.println(service.take().get());  
  46.         }  
  47.     }  
  48. }  

 

 

lock,,,普通锁,,以及读写锁,,可以实现读与写之间互斥,读于读之间可以并行,写于写之间也互斥!!

面试题一道,,通过读写锁编写一个缓存类得实际应用

 

  1. package concurrent;  
  2.   
  3. import java.util.*;  
  4. import java.util.concurrent.locks.ReadWriteLock;  
  5. import java.util.concurrent.locks.ReentrantReadWriteLock;  
  6.   
  7. public class CacheClass {  
  8.     public static void main(String[] args) {  
  9.         //test();   
  10.     }  
  11.     private ReadWriteLock rwl = new ReentrantReadWriteLock();  
  12.     private Map<String,Object> cacheData = new HashMap<String,Object>();  
  13.     public Object get(String key){  
  14.         rwl.readLock().lock();  
  15.         Object obj = null;  
  16.         try {  
  17.             obj = cacheData.get(key);  
  18.             if(obj==null){  
  19.                 rwl.readLock().unlock();  
  20.                 rwl.writeLock().lock();  
  21.                 obj = "Shawn";//readDatabase();   
  22.                 cacheData.put(key, obj);  
  23.                 rwl.writeLock().unlock();  
  24.                 rwl.readLock().lock();  
  25.             }  
  26.         } finally {  
  27.             rwl.readLock().unlock();  
  28.         }  
  29.           
  30.         return obj;  
  31.     }  
  32. }  

 

 

以及通过面向对象设计的一另一道面试题,,子线程执行5次,主线程执行10次,这样循环总共10次。。。通过synchronized关键字修饰子线程和主线程需要执行的方法封装到一个类当中,通过一个boolean变量来标识子线程和主线程的执行次序。。。然后各自循环10次。。。同样实现两个子线程和一个主线程来交替执行,这个时候就需要用到显示锁,通过多个条件变量(condition)来实现,,线程1获得锁,执行完释放并通知条件变量2,线程2获得锁,执行完释放并通知条件变量3,以此类推,,4个或5个线程交替执行也同理!!!

 

  1. package concurrent;  
  2.   
  3. public class InterViewSubject {  
  4.     public static void main(String[] args) {  
  5.         init();  
  6.     }  
  7.   
  8.     private static void init() {  
  9.         final MyData data = new MyData();  
  10.         new Thread() {  
  11.             public void run() {  
  12.                 for (int i = 0; i < 10; i++) {  
  13.                     data.sub();  
  14.                 }  
  15.             }  
  16.         }.start();  
  17.         for (int i = 0; i < 10; i++) {  
  18.             data.main();  
  19.         }  
  20.     }  
  21. }  
  22.   
  23. class MyData {  
  24.     private boolean isMain;  
  25.   
  26.     public synchronized void sub() {  
  27.         if (!isMain) {  
  28.             for (int i = 0; i < 5; i++) {  
  29.                 System.out.println("sub Thread loop for : " + i);  
  30.             }  
  31.         } else  
  32.             try {  
  33.                 this.wait();  
  34.             } catch (InterruptedException e) {  
  35.                 e.printStackTrace();  
  36.             }  
  37.         isMain = true;  
  38.         this.notify();  
  39.     }  
  40.   
  41.     public synchronized void main() {  
  42.         if (isMain) {  
  43.             for (int i = 0; i < 10; i++) {  
  44.                 System.out.println("main Thread loop for : " + i);  
  45.             }  
  46.         } else  
  47.             try {  
  48.                 this.wait();  
  49.             } catch (InterruptedException e) {  
  50.                 e.printStackTrace();  
  51.             }  
  52.         isMain = false;  
  53.         this.notify();  
  54.     }  
  55. }  

 

 

 

  欢迎大家评论,,大家能够讨论讨论咱们所学的知识点有些什么实际应用场景!!!这也是我们最终学习新知识的最终目的!!!

 

出自:http://blog.csdn.net/a15874647/article/details/6440998

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章