并发concurrent---2

背景:并发知识是一个程序员段位升级的体现,一样也是进入BAT的必经之路,有必要把并发知识从新梳理一遍。java

 

并发concurrent:程序员

使用ThreadLocal能够实现线程范围内共享变量,线程A写入的值和线程B获取到的结果一致;ReentrantReadWriteLock容许多个读线程或多个写线程同时进行,但不容许写线程和读线程同时进行;使用Callable能够获得线程执行的返回结果;Exchanger能够相互交换家线程执行的结果;这些使用方法大体都同样,JDk参考文档里面哪里不会点哪里,下面写个ThreadLocal实现线程范围内变量共享,里面还用到了一下饿汉模式:面试

执行结果如图中控制台打印,使用ThreadLocal保证了线程0和线程1读取到的值与写入的一致。算法

 1 import java.util.Random;  2 import java.util.concurrent.locks.ReentrantReadWriteLock;  3 import lombok.Data;  4 
 5 public class ThreadLocalTest {  6     //ThreadLocal 实现线程范围内共享变量
 7     private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();  8     private static ThreadLocal<MyThreadScopeData> myThreadScopeData = new ThreadLocal<MyThreadScopeData>();  9     public static void main(String[] args) { 10         new ReentrantReadWriteLock(); 11         for(int i = 0; i<2; i++) { 12             new Thread(new Runnable() { 13  @Override 14                 public void run() { 15                     int data = new Random().nextInt(); 16  System.out.println(Thread.currentThread().getName() 17                             +" has put data: "+ data); 18                     x.set(data);  // 存的时候与当前线程相关 取的时候也是与当前线程相关 19                     //MyThreadScopeData.getInstance()拿到与本线程实例相关的对象: 不用反复new对象来getter/setter
20                     MyThreadScopeData.getThreadInstance().setName("name: "+data); 21  MyThreadScopeData.getThreadInstance().setAge(data); 22                     new A().get(); 23                     new B().get(); 24  } 25  }).start(); 26  } 27 } 28     
29     static class A{ 30         public void get() { 31             int data = x.get(); 32             System.out.println("A from "+Thread.currentThread().getName()+" get data: "+data); 33             //MyThreadScopeData.getInstance()拿到与本线程实例相关的对象
34             MyThreadScopeData myData = MyThreadScopeData.getThreadInstance(); 35             System.out.println("A from "+Thread.currentThread().getName() 36                     +" getMyData: "+myData.getName() +","+myData.getAge()); 37  } 38  } 39     
40     static class B{ 41         public void get() { 42             int data = x.get(); 43             System.out.println("B from "+Thread.currentThread().getName()+" get data: "+data); 44             //MyThreadScopeData.getInstance()拿到与本线程实例相关的对象
45             MyThreadScopeData myData = MyThreadScopeData.getThreadInstance(); 46             System.out.println("B from "+Thread.currentThread().getName() 47                     +" getMyData: "+myData.getName() +","+myData.getAge()); 48  } 49  } 50     
51     //设计本身线程范围内变量的共享,不须要建立对象,只需调用线程便可用到线程内的变量
52  @Data 53     static class MyThreadScopeData{ 54         //构造方法私有化,外部没发直接调用,可是能够调用里面的静态方法
55         private MyThreadScopeData() { } 56         public static /*synchronized*/ MyThreadScopeData getThreadInstance() { 57             MyThreadScopeData instance = map.get(); 58             if (instance == null) { 59                 //饿汉模式 : 第一次来建立
60                 instance = new MyThreadScopeData(); 61  map.set(instance); 62  } 63             return instance; 64  } 65     // private static MyThreadScopeData instance = null; // new MyThreadScopeData();
66         private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>(); 67         private String name; 68         private int age; 69  } 70 
71 }

网上还有一个多线程面试颇有趣的题目:子线程执行10次,主线程执行100次,接着子线程再执行10次,主线程继续再执行100次,往复循环50次;spring

 1 //Java多线程面试: 子线程执行10次,主线程执行100次,接着子线程再10次,主线程再执行100次,往复循环50次
 2 public class ThreadCommunication {  3     public static void main(String[] args) {  4      Business business = new Business();  5     new Thread(  6             new Runnable() {  7  @Override  8         public void run() {  9             for (int i = 1; i <= 50; i++) { 10  business.sub(i); 11  } 12  } 13  }).start(); 14     
15     for (int i = 1; i <= 50; i++) { 16  business.main(i); 17  } 18  } 19     
20     //把主线程和自线程执行的方法归结到一个类(共同算法的若干方法),巧妙设计,好维护高聚合,健壮性;
21     public static class Business{ 22         //子线程方法
23         private boolean bShouldSub = true; 24         public synchronized void sub(int i) { 25             while(!bShouldSub) { 26                 //用while比if更好,能够防止线程被伪唤醒
27                 try { 28                     this.wait(); // 若是不是子线程方法该执行的,则令其等待
29                 } catch (InterruptedException e) { 30  e.printStackTrace(); 31  } 32  } 33             for(int j = 1; j<= 10; j++) { 34                 System.out.println("sub thread sequence of "+j + ",loop of "+ i); 35  } 36             bShouldSub = false; 37             this.notify(); //唤醒主线程方法
38  } 39     
40     //主线程方法
41     public synchronized void main(int i) { 42         while(!bShouldSub) { 43             try { 44                 this.wait();  // 若是不是主线程方法该执行的,则令其等待
45             } catch (InterruptedException e) { 46  e.printStackTrace(); 47  } 48  } 49         for(int j = 1; j<= 100; j++) { 50             System.out.println("main thread sequence of "+j + ",loop of "+ i); 51  } 52         bShouldSub = true; 53         this.notify();  // 唤醒子线程方法
54  } 55  } 56 }

线程池:缓存

一、固定线程数目的线程池newFixedThreadPool;多线程

二、缓存线程数目的线程池newCachedThreadPool;并发

三、单一线程池newSingleThreadExecutor;dom

四、定时器线程池newScheduledThreadPool;ide

 1 package com.xinyan.springcloud.controller;  2 
 3 import java.util.concurrent.ExecutorService;  4 import java.util.concurrent.Executors;  5 import java.util.concurrent.TimeUnit;  6 
 7 public class ThreadPoolTest {  8     public static void main(String[] args) {  9         //固定线程数目的线程池 3个
10          ExecutorService threadPool = Executors.newFixedThreadPool(3); 11         //缓存线程数目的线程池即动态变化 当任务过来了,线程池内部会自动增长线程,空闲后线程又被回收,线程数目不定 12         //ExecutorService threadPool = Executors.newCachedThreadPool(); 13         //单一线程池 14         //ExecutorService threadPool = Executors.newSingleThreadExecutor(); 15         //往线程池中放入10个任务:
16         for(int i = 1; i<= 10; i++) { 17             final int task = i; // task被final修饰不能变了,可是i 能够变
18             threadPool.execute(new Runnable() { 19  @Override 20                 public void run() { 21                     for(int j =1; j<=10; j++) { 22                         try { 23                             Thread.sleep(200); 24                         } catch (InterruptedException e) { 25  e.printStackTrace(); 26  } 27                         //System.out.println(Thread.currentThread().getName()+" loop of "+ j +" task is "+ task);
28  } 29  } 30  }); 31  } 32         System.out.println("全部的10个任务已经所有提交。");   //任务都提交了,交由线程池去搞
33         threadPool.shutdown();   //没有任务后关闭线程 34           //threadPool.shutdownNow(); //还有任务没有给执行完毕就当即关闭线程 35         
36         //定时器线程池: 3个线程 
37         System.out.println("敌军还有5秒到达战场."); 38         Executors.newScheduledThreadPool(3).schedule(new Runnable() { 39  @Override 40             public void run() { 41                 System.out.println("敌军抵达战场,碾碎她们。"); 42  } 43             //5秒后执行线程池内run方法
44         }, 5, TimeUnit.SECONDS); 45         //Executors.newScheduledThreadPool(3)scheduleAtFixedRate(command, initialDelay, period, unit) 46         //scheduleAtFixedRate 定时循环执行线程池内方法
47  } 48 }
相关文章
相关标签/搜索