Java多线程与并发库高级应用
来源:互联网 发布:手机画图软件排行 编辑:程序博客网 时间:2024/05/21 08:33
Java 线程并发 名词解释
- Concurrent 同时
- Atomic 原子
- Callable 可调用
- Future 将来
- Condition 条件
- Reentrant 重入
- Semaphore 信号
- Signal 信号,信号量
- Cyclic 循环
- Barrier 屏障
- Latch 闩
- Exchanger 交换器
- Mutex 互斥
涉及内容
- 创建线程 new Thread();
- 创建定时器 new TimerTask();
- synchronized 关键字的使用
- ThreadLocal 的使用
- 多个线程间共享数据
- Java 原子性
- 创建线程池
- 线程执行完成的回调 Future 和 CompletionService
- 锁Lock
- 可重入的互斥锁 ReentrantLock
- 读写锁 ReentrantReadWriteLock
- Lock的 阻塞Condition
- Semaphore信号量
- CyclicBarrier循环阻塞
- CountdownLatch 非零0等待,0执行
- Exchanger线程间交换数据
- BlockingQueue 阻塞队列
- SynchronousQueue 阻塞同步队列
- 集合并发操作的ConcurrentModificationException
总结
- Lock 普通锁,与 synchronized 关键字功能相同,都是多线程互斥等待
- ReadWriteLock 读写锁,读与读并行,读与写互斥,写与写互斥
- Condition 条件互斥,与线程的 this.wait(); 和 this.notify(); 功能相同
- BoundedBuffer 使用 双Condition 完成 存与取 的阻塞
- Semaphore 信号量,比 Lock 更灵活
- CyclicBarrier 循环阻塞 只有当 指定数量的线程到达,才会继续执行
- CountdownLatch 非零0等待,0执行
- Exchanger 线程与线程间交换数据
BlockingQueue 阻塞队列,队列满后阻塞,队列非满,按顺序插入
SynchronousQueue 阻塞同步队列
传统方式创建一个线程
// 1. Thread thread = new Thread() { /** * 重写 run() 方法 */ @Override public void run() { while (true) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } // 获取当前线程名称 System.out.println("1:" + Thread.currentThread().getName()); // 获取当前线程名称 this 指当前线程 System.out.println("2:" + this.getName()); } } }; thread.start();// 执行 // 2. Thread thread2 = new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("1:" + Thread.currentThread().getName()); } } }); thread2.start(); // 3. new Thread( /** * 底层实现 在 run() 方法中执行 Runnable() */ new Runnable(){ public void run() { while(true){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("runnable :" + Thread.currentThread().getName()); } } } )// Thread 的方法参数 { /** * 重写父类的 run() 方法 * 此处没有调用父类的 run() 方法 ,所以上面的 Runnbale() 方法无法执行 */ @Override public void run() { while(true){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread :" + Thread.currentThread().getName()); } } }.start();
传统方式创建一个定时器
// 输出 main() 方法 执行所在的线程 System.out.println("main() : "+Thread.currentThread().getName()); // main() : main // 1. 创建一个 延迟 3s 的 Timer ,只执行一次 /*new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("Timer 1: "+Thread.currentThread().getName()); // Timer 1: Timer-0 System.out.println("bombing"); } }, 3000);*/ // 2. 创建一个 Timer 第一次延迟10s 执行,之后间隔 3s 执行 /*new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("Timer 2: "+Thread.currentThread().getName()); // Timer 2: Timer-0 System.out.println("bombing!"); } }, 10000, 3000);*/ // 3. 自定一个 TimerTask 实现 每隔 2s 执行一次 class MyTimerTask extends TimerTask{ @Override public void run() { /* Timer 没有循环利用,每次都是生成一个 新的 Timer Timer 3: Timer-0 bombing! Timer 3: Timer-1 bombing! Timer 3: Timer-2 bombing! Timer 3: Timer-3 bombing! Timer 3: Timer-4 bombing! Timer 3: Timer-5 bombing! Timer 3: Timer-6 bombing! Timer 3: Timer-7 bombing! Timer 3: Timer-8 bombing! Timer 3: Timer-9 bombing! Timer 3: Timer-10 bombing! ... */ System.out.println("Timer 3: "+Thread.currentThread().getName()); System.out.println("bombing!"); // TimerTask 内部 在调用 Timer() 执行自己 new Timer().schedule(/*new TimerTask() { @Override public void run() { System.out.println("bombing!"); // 此处只执行一次,如果需要实现每个 2s 执行一次, // 需要 再 启动一个 Timer //new Timer().schedule(new TimerTask(){}, 2000); } }*/new MyTimerTask(),2000);//类似 递归方式 ,new 一个 TimerTask() } } // 入口 Timer() new Timer().schedule(new MyTimerTask(), 2000);
- 开源框架:基于 Quartz 开发企业级任务调度应用
- 案例:工作日发送邮件,周末休息
传统的 线程互斥技术
public static void main(String[] args) { // 静态方法访问 内部类 无法编译通过,编译器报错 // 因为 内部类 共享外部类的 成员变量和方法,静态方法创建时,外部类的对象并未创建,这与内部类的定义相矛盾 // 使用对象方法 包装 内部类 new _3_TraditionalThreadSynchronized().init(); } private void init() { final Outputer outputer = new Outputer(); new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangxiaoxiang"); } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } // outputer.output2("lihuoming"); // outputer.output3("lihuoming"); } } }).start(); } static class Outputer { public void output(String name) { int len = name.length(); // synchronized (this) // 此时与 output2 生成互斥锁,互斥对象是 当前类 synchronized (Outputer.class) // 此时与 output3 生成互斥锁,互斥对象是 类对象 { for (int i = 0; i < len; i++) { System.out.print(name.charAt(i)); } System.out.println(); } } /** * 互斥锁 为 synchronized (this) * @param name */ public synchronized void output2(String name) { int len = name.length(); for (int i = 0; i < len; i++) { System.out.print(name.charAt(i)); } System.out.println(); } /** * 互斥锁 为 synchronized (Outputer.class) * @param name */ public static synchronized void output3(String name) { int len = name.length(); for (int i = 0; i < len; i++) { System.out.print(name.charAt(i)); } System.out.println(); } }
传统的线程间通讯
public class _4_TraditionalThreadCommunication { public static void main(String[] args) { // 1. 主线程 和 子线程 分别 执行 从 0 - 9 不可被打断,各执行 50 次 /* new Thread(new Runnable() { @Override public void run() { synchronized (ExampleUnitTest.class) { for (int i = 0; i < 50; i++) { for (int j = 0; j < 10; j++) { System.out.println("sub i:" + i + " j:" + j); } } } } }).start(); synchronized (ExampleUnitTest.class) { for (int i = 0; i < 50; i++) { for (int j = 0; j < 10; j++) { System.out.println("main i:" + i + " j:" + j); } } }*/ // 2. 子线程 执行 10次,主线程执行 100 次,交替执行 50次,中间不被打断 /*final Business business = new Business(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i <= 50; i++) { business.sub(i); } } }).start(); for (int i = 1; i <= 50; i++) { business.main(i); }*/ } static class Business { private boolean bShouldSub = true;// 控制是否是子线程 public synchronized void sub(int i) { // if(!bShouldSub) // 如果使用 if 可能会出现 伪唤醒,while 比 if 精确。原因:if 语句只会执行一次,如果被notify()但是条件并没有满足,后续代码就会执行,出现错误。while 会判断条件是否满足 while (!bShouldSub) {// 如果主线程在执行,bShouldSub = false,进入循环,当前线程 wait() try { this.wait();// 等待 } catch (InterruptedException e) { e.printStackTrace(); } } // 执行 for (int j = 0; j < 10; j++) { System.out.println("sub i:" + i + " j:" + j); } // 执行完成 bShouldSub = false; // 唤醒等待的 wait() 的线程 this.notify(); } public synchronized void main(int i) { // if(bShouldSub) // 如果使用 if 可能会出现 伪唤醒,while 比 if 精确。原因:if 语句只会执行一次,如果被notify()但是条件并没有满足,后续代码就会执行,出现错误。while 会判断条件是否满足 while (bShouldSub) {// 如果主线程在执行,bShouldSub = true ,进入循环,主线程 wait(); try { this.wait();// 等待 } catch (InterruptedException e) { e.printStackTrace(); } } // 执行 for (int j = 0; j < 100; j++) { System.out.println("main i:" + i + " j:" + j); } // 执行完成 bShouldSub = true; // 唤醒等待的 wait() 的线程 this.notify(); } } /** * 这种做法 无法实现,需要 手动去切换执行线程,废弃 * * @author Wjz * */ static class Business2 { private boolean bShouldSub = true; public synchronized void sub(int i) { if (bShouldSub) { // 执行 for (int j = 0; j < 10; j++) { System.out.println("sub i:" + i + " j:" + j); } bShouldSub = false; } } public synchronized void main(int i) { if (!bShouldSub) {// 执行 for (int j = 0; j < 100; j++) { System.out.println("main i:" + i + " j:" + j); } bShouldSub = true; } } }}
线程范围共享变量
// 1. HashMap 方式,使用 Thread 对象 作为 key private static Map<Thread, Integer> threadData = new HashMap<Thread, Integer>(); public static void main(String[] args) { for(int i=0;i<2;i++){ new Thread(new Runnable(){ @Override public void run() { int data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " has put data :" + data); threadData.put(Thread.currentThread(), data); new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ int data = threadData.get(Thread.currentThread()); System.out.println("A from " + Thread.currentThread().getName() + " get data :" + data); } } static class B{ public void get(){ int data = threadData.get(Thread.currentThread()); System.out.println("B from " + Thread.currentThread().getName() + " get data :" + data); } } // 2. ThreadLocal 方式 private static ThreadLocal<Integer> x = new ThreadLocal<Integer>(); public static void main(String[] args) { for(int i=0;i<2;i++){ new Thread(new Runnable(){ @Override public void run() { int data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " has put data :" + data); x.set(data); new A().get(); new B().get(); } }).start(); } } static class A{ public void get(){ int data = x.get(); System.out.println("A from " + Thread.currentThread().getName() + " get data :" + data); } } static class B{ public void get(){ int data = x.get(); System.out.println("B from " + Thread.currentThread().getName() + " get data :" + data); } } // 3. 优雅的 ThreadLocal 方式 // 普通方式:ThreadLocal 暴露在调用方 // 高雅方式:将 ThreadLocal 封装到使用方 private static ThreadLocal<MyThreadScopeData> tData= new ThreadLocal<MyThreadScopeData>(); public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { int data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " has put data :" + data); /* 1. 普通方式 MyThreadScopeData myData = new MyThreadScopeData(); myData.setName("name" + data); myData.setAge(data); tData.set(myData); */ // 2. 高级优雅方式 MyThreadScopeData.getThreadInstance().setName("name" + data); MyThreadScopeData.getThreadInstance().setAge(data); new A().get(); new B().get(); } }).start(); } } static class A { public void get() { /* 1. 普通方式 MyThreadScopeData myData = myThreadScopeData.get();; System.out.println("A from " + Thread.currentThread().getName() + " getMyData: " + myData.getName() + "," + myData.getAge()); */ // 2. 高级优雅方式 MyThreadScopeData myData = MyThreadScopeData.getThreadInstance(); System.out .println("A from " + Thread.currentThread().getName() + " getMyData: " + myData.getName() + "," + myData.getAge()); } } static class B { public void get() { MyThreadScopeData myData = MyThreadScopeData.getThreadInstance(); System.out .println("B from " + Thread.currentThread().getName() + " getMyData: " + myData.getName() + "," + myData.getAge()); } }}/** * 在当前类中 封装 ThreadLocal * * @author Wjz * */class MyThreadScopeData { private MyThreadScopeData() { } /** * private static MyThreadScopeData instance = null; 饥汉 模式 //new MyThreadScopeData(); 饱汉 模式 */ private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>(); /** * 每个线程都有独立的 ThreadLocal 因此不需要 同步 * * @return */ public static/*synchronized*/MyThreadScopeData getThreadInstance() { MyThreadScopeData instance = map.get(); if (instance == null) { instance = new MyThreadScopeData(); map.set(instance); } return instance; } private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }
多个线程之间共享数据
public class _8_MultiThreadShareData { private int j; public static void main(String[] args) { // 设计4个线程,其中两个线程每次对j增加1,各100次,另外两个线程对j每次减1,各100次。 // 以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。 _8_MultiThreadShareData _8 = new _8_MultiThreadShareData(); Inc inc = _8.new Inc(); Dec dec = _8.new Dec(); for (int i = 0; i < 2; i++) { Thread thread = new Thread(inc); thread.start(); thread = new Thread(dec); thread.start(); } } /** * 需要多个线程同时访问,增加 同步关键字 */ private synchronized void inc() { j++; System.out.println(Thread.currentThread().getName()+" -inc: "+j); } /** * 需要多个线程同时访问,增加 同步关键字 */ private void dec(){ j--; System.out.println(Thread.currentThread().getName()+" -dec: "+j); } class Inc implements Runnable{ @Override public void run() { for(int i=0;i<100;i++){ inc(); } } } class Dec implements Runnable{ @Override public void run() { for(int i=0;i<100;i++){ dec(); } } }}
public class _9_MultiThreadShareData2 { // 方法一,静态成员对象 private static ShareData1 data1 = new ShareData1(); public static void main(String[] args) { // 1. 方法一 final ShareData1 data1 = new ShareData1(); new Thread(new Runnable() { @Override public void run() { data1.decrement(); } }).start(); new Thread(new Runnable() { @Override public void run() { data1.increment(); } }).start(); // 2. 方法二 传递对象 到具体的逻辑对象 ShareData1 data2 = new ShareData1(); new Thread(new MyRunnable1(data2)).start(); new Thread(new MyRunnable2(data2)).start(); }}/** * 传递对象,实现 减法 操作 * * @author Wjz * */class MyRunnable1 implements Runnable { private ShareData1 data1; public MyRunnable1(ShareData1 data1) { this.data1 = data1; } public void run() { data1.decrement(); }}/** * 传递对象,实现 加法 操作 * * @author Wjz * */class MyRunnable2 implements Runnable { private ShareData1 data1; public MyRunnable2(ShareData1 data1) { this.data1 = data1; } public void run() { data1.increment(); }}class ShareData1 /*implements Runnable*/{ /* private int count = 100; @Override public void run() { while(true){ count--; } }*/ private int j = 0; public synchronized void increment() { j++; } public synchronized void decrement() { j--; }}
Java 线程原子性操作
Atomic
所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
Java 线程池
// ExecutorService threadPool = Executors.newFixedThreadPool(3); // ExecutorService threadPool = Executors.newCachedThreadPool(); ExecutorService threadPool = Executors.newSingleThreadExecutor(); for (int i = 1; i <= 10; i++) { final int task = i; threadPool.execute(new Runnable() { @Override public void run() { for (int j = 1; j <= 10; j++) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is looping of " + j + " for task of " + task); } } }); } System.out.println("all of 10 tasks have committed! "); // 关闭线程 // threadPool.shutdown(); // threadPool.shutdownNow(); Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("bombing!"); } }, 6, 2, TimeUnit.SECONDS);
Java线程完成回调 Callable与Future和CompletionService
// Callable -> Future ExecutorService threadPool = Executors.newSingleThreadExecutor(); Future<String> future = threadPool.submit(new Callable<String>() { public String call() throws Exception { Thread.sleep(2000); return "hello"; }; }); System.out.println("等待结果"); try { // 10s 就要收到回调结果,否则报 TimeoutException System.out.println("拿到结果:" + future.get(10, TimeUnit.SECONDS)); // 一直等待回调结果 // System.out.println("拿到结果:" + future.get()); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (ExecutionException e1) { e1.printStackTrace(); } catch (TimeoutException e1) { e1.printStackTrace(); } // Multi Callable -> Multi CompletionService ExecutorService threadPool2 = Executors.newFixedThreadPool(10); CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2); for (int i = 1; i <= 10; i++) { final int seq = i; completionService.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { Thread.sleep(new Random().nextInt(5000)); return seq; } }); } for (int i = 0; i < 10; i++) { try { System.out.println(completionService.take().get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
Java 线程锁 Lock
与 synchronized 效果相同,Lock 更加面向对象
public static void main(String[] args) { new _12_Lock().init(); } private void init(){ final Outputer outputer = new Outputer(); new Thread(new Runnable(){ @Override public void run() { while(true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangxiaoxiang"); } } }).start(); new Thread(new Runnable(){ @Override public void run() { while(true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("lihuoming"); } } }).start(); } static class Outputer{ /** * synchronized 关键字效果 相同 * ReentrantLock: Lock 接口的实现类 */ Lock lock = new ReentrantLock(); public void output(String name){ int len = name.length(); lock.lock(); try{ for(int i=0;i<len;i++){ System.out.print(name.charAt(i)); } System.out.println(); }finally{ // 上锁后 如果抛异常 需要被被释放 lock.unlock(); } } }
Java 读写锁 ReentrantReadWriteLock()
public class _13_ReadWriteLock { public static void main(String[] args) { // 自定义Queue3对象 final Queue3 q3 = new Queue3(); for(int i=0;i<3;i++) { new Thread(){ public void run(){ while(true){ q3.get(); } } }.start(); new Thread(){ public void run(){ while(true){ q3.put(new Random().nextInt(10000)); } } }.start(); } }}class Queue3{ //共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。 private Object data = null; ReadWriteLock rwl = new ReentrantReadWriteLock(); /** * 读数据 */ public void get(){ rwl.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + " be ready to read data!"); Thread.sleep((long)(Math.random()*1000)); System.out.println(Thread.currentThread().getName() + "have read data :" + data); } catch (InterruptedException e) { e.printStackTrace(); }finally{ rwl.readLock().unlock(); } } /** * 写数据 * @param data */ public void put(Object data){ rwl.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + " be ready to write data!"); Thread.sleep((long)(Math.random()*1000)); this.data = data; System.out.println(Thread.currentThread().getName() + " have write data: " + data); } catch (InterruptedException e) { e.printStackTrace(); }finally{ rwl.writeLock().unlock(); } }}
// 官方案例 读取缓存数据 伪代码class CachedData { Object data; volatile boolean cacheValid; ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock(); rwl.writeLock().lock(); // 如果多个线程同时阻塞在此处,等一个线程完成,需要更新状态,否则其他线程依然会进入 // Recheck state because another thread might have acquired // write lock and changed state before we did. if (!cacheValid) { data = ... cacheValid = true;// 更新状态 } // Downgrade by acquiring read lock before releasing write lock // 在释放写入锁定之前通过获取读取锁定进行降级 // 写锁降级,降级更新锁 rwl.readLock().lock(); rwl.writeLock().unlock(); // Unlock write, still hold read } use(data); rwl.readLock().unlock(); } }
Java 阻塞Condition
/** * 与 _4_TraditionalThreadCommunication * 使用 synchronized * this.wait(); * this.notify(); * 功能相同 * @author Wjz * */public class _14_ConditionCommunication { public static void main(String[] args) { final Business business = new Business(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i <= 50; i++) { business.sub(i); } } }).start(); for (int i = 1; i <= 50; i++) { business.main(i); } } /** * 静态内部类 _14_ConditionCommunication.Business * 外部类 Business 包名相同会冲突 * * @author Wjz * */ static class Business { Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); private boolean bShouldSub = true; public void sub(int i) { lock.lock(); try { while (!bShouldSub) { try { condition.await(); } catch (Exception e) { e.printStackTrace(); } } for (int j = 1; j <= 10; j++) { System.out.println("sub thread sequence of " + j + ",loop of " + i); } bShouldSub = false; condition.signal(); } finally { lock.unlock(); } } public void main(int i) { lock.lock(); try { while (bShouldSub) { try { condition.await(); } catch (Exception e) { e.printStackTrace(); } } for (int j = 1; j <= 100; j++) { System.out.println("main thread sequence of " + j + ",loop of " + i); } bShouldSub = true; condition.signal(); } finally { lock.unlock(); } } }}
/** * 阻塞式队列的实现原理 * @author Wjz * */public class _15_BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); // Buffer 总长度 final Object[] items = new Object[100]; int putptr, takeptr, count; /** * 存入数据 * @param x * @throws InterruptedException */ public void 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(); } } /** * 取出数据 * @return * @throws InterruptedException */ public Object take() throws InterruptedException { 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(); } }}
/** * 根据 _14_ConditionCommunication 案例 增加多个线程间通讯 * * @author Wjz * */public class _16_MultiConditionCommunication { public static void main(String[] args) { final Business business = new Business(); // 子线程 1 new Thread(new Runnable() { @Override public void run() { for (int i = 1; i <= 50; i++) { business.sub2(i); } } }).start(); // 子线程 2 new Thread(new Runnable() { @Override public void run() { for (int i = 1; i <= 50; i++) { business.sub3(i); } } }).start(); // 主线程 for (int i = 1; i <= 50; i++) { business.main(i); } } static class Business { Lock lock = new ReentrantLock(); Condition condition1 = lock.newCondition();// 主线程的条件控制锁 Condition condition2 = lock.newCondition();// 子线程1的条件控制锁 Condition condition3 = lock.newCondition();// 子线程2的条件控制锁 private int shouldSub = 1;// 断点记录 public void sub2(int i) { lock.lock(); try { while (shouldSub != 2) { try { condition2.await(); } catch (Exception e) { e.printStackTrace(); } } for (int j = 1; j <= 10; j++) { System.out.println("sub2 thread sequence of " + j + ",loop of " + i); } // 线程2唤醒线程3 shouldSub = 3; condition3.signal(); } finally { lock.unlock(); } } public void sub3(int i) { lock.lock(); try { while (shouldSub != 3) { try { condition3.await(); } catch (Exception e) { e.printStackTrace(); } } for (int j = 1; j <= 20; j++) { System.out.println("sub3 thread sequence of " + j + ",loop of " + i); } // 线程2唤醒主线程 shouldSub = 1; condition1.signal(); } finally { lock.unlock(); } } public void main(int i) { lock.lock(); try { while (shouldSub != 1) { try { condition1.await(); } catch (Exception e) { e.printStackTrace(); } } for (int j = 1; j <= 100; j++) { System.out.println("main thread sequence of " + j + ",loop of " + i); } // 主线程唤醒线程2 shouldSub = 2; condition2.signal(); } finally { lock.unlock(); } } }}
Java 线程Semaphore信号量
比 Lock + Condition 灵活
public class _17_Semaphore { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Semaphore sp = new Semaphore(3); for (int i = 0; i < 10; i++) { Runnable runnable = new Runnable() { public void 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(); }finally{ System.out.println("线程" + Thread.currentThread().getName() + "即将离开"); // 释放一个许可,将其返回给信号量。 sp.release(); } // 下面代码有时候执行不准确,因为其没有和上面的代码合成 原子 单元 System.out.println("线程" + Thread.currentThread().getName() + "已离开,当前已有" + (3 - sp.availablePermits()) + "个并发"); } }; // newCachedThreadPool 会创建10个线程并发 service.execute(runnable); /*线程pool-1-thread-1进入,当前已有3个并发线程pool-1-thread-2进入,当前已有3个并发线程pool-1-thread-3进入,当前已有3个并发线程pool-1-thread-1即将离开线程pool-1-thread-1已离开,当前已有2个并发线程pool-1-thread-4进入,当前已有3个并发线程pool-1-thread-2即将离开线程pool-1-thread-2已离开,当前已有2个并发线程pool-1-thread-5进入,当前已有3个并发线程pool-1-thread-5即将离开线程pool-1-thread-5已离开,当前已有2个并发线程pool-1-thread-8进入,当前已有3个并发线程pool-1-thread-8即将离开线程pool-1-thread-8已离开,当前已有2个并发线程pool-1-thread-6进入,当前已有3个并发线程pool-1-thread-3即将离开线程pool-1-thread-3已离开,当前已有2个并发线程pool-1-thread-10进入,当前已有3个并发线程pool-1-thread-4即将离开线程pool-1-thread-4已离开,当前已有2个并发线程pool-1-thread-7进入,当前已有3个并发线程pool-1-thread-10即将离开线程pool-1-thread-10已离开,当前已有2个并发线程pool-1-thread-9进入,当前已有3个并发线程pool-1-thread-7即将离开线程pool-1-thread-7已离开,当前已有2个并发线程pool-1-thread-6即将离开线程pool-1-thread-6已离开,当前已有1个并发线程pool-1-thread-9即将离开线程pool-1-thread-9已离开,当前已有0个并发 */ } }}
Java 线程 循环阻塞
public class _18_CyclicBarrier { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CyclicBarrier cb = new CyclicBarrier(3); for(int i=0;i<3;i++){ Runnable runnable = new Runnable(){ public void run(){ try { Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); // 阻塞1,只有当3个线程同时到达,才会继续向下 cb.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); // 阻塞2, 只有当3个线程同时到达,才会继续向下 cb.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); // 阻塞3,只有当3个线程同时到达,才会继续向下 cb.await(); } catch (Exception e) { e.printStackTrace(); } } }; service.execute(runnable); } service.shutdown(); }}
Java 线程 CountdownLatch
public class _19_CountdownLatch { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CountDownLatch cdOrder = new CountDownLatch(1); // 主线程控制,为0 继续向下执行,初始化为1 final CountDownLatch cdAnswer = new CountDownLatch(3); // 子线程控制,为0 继续向下执行,初始化为3 for (int i = 0; i < 3; i++) { Runnable runnable = new Runnable() { public void run() { try { System.out.println("线程" + Thread.currentThread().getName() + "正准备接受命令"); // 等待主线程控制 -1 cdOrder.await(); System.out.println("线程" + Thread.currentThread().getName() + "已接受命令"); Thread.sleep((long) (Math.random() * 10000)); System.out .println("线程" + Thread.currentThread().getName() + "回应命令处理结果"); // cdAnswer -1 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() + "已发送命令,正在等待结果"); // 等待 3个 子线程 -1 cdAnswer.await(); System.out.println("线程" + Thread.currentThread().getName() + "已收到所有响应结果"); } catch (Exception e) { e.printStackTrace(); } service.shutdown(); /*线程pool-1-thread-1正准备接受命令线程pool-1-thread-3正准备接受命令线程pool-1-thread-2正准备接受命令线程main即将发布命令线程main已发送命令,正在等待结果线程pool-1-thread-1已接受命令线程pool-1-thread-2已接受命令线程pool-1-thread-3已接受命令线程pool-1-thread-3回应命令处理结果线程pool-1-thread-1回应命令处理结果线程pool-1-thread-2回应命令处理结果线程main已收到所有响应结果 */ }}
Java 线程 Exchanger
public class _20_Exchanger { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Exchanger exchanger = new Exchanger(); service.execute(new Runnable() { public void run() { try { String data1 = "zxx"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 + "换出去"); Thread.sleep((long) (Math.random() * 10000)); String data2 = (String) exchanger.exchange(data1); System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2); } catch (Exception e) { } } }); service.execute(new Runnable() { public void run() { try { String data1 = "lhm"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 + "换出去"); Thread.sleep((long) (Math.random() * 10000)); String data2 = (String) exchanger.exchange(data1); System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2); } catch (Exception e) { } } }); /*线程pool-1-thread-1正在把数据zxx换出去线程pool-1-thread-2正在把数据lhm换出去线程pool-1-thread-1换回的数据为lhm线程pool-1-thread-2换回的数据为zxx */ }}
Java 多线程 BlockingQueue 阻塞队列
// BlockingQueue 阻塞队列 的使用public class _21_BlockingQueue { public static void main(String[] args) { /*Thread-1准备放数据!Thread-1已经放了数据,队列目前有1个数据Thread-0准备放数据!Thread-0已经放了数据,队列目前有2个数据Thread-1准备放数据!Thread-1已经放了数据,队列目前有3个数据Thread-2准备取数据!Thread-2已经取走数据,队列目前有2个数据Thread-0准备放数据!Thread-0已经放了数据,队列目前有3个数据Thread-1准备放数据!Thread-0准备放数据!Thread-2准备取数据!Thread-2已经取走数据,队列目前有2个数据Thread-1已经放了数据,队列目前有3个数据Thread-1准备放数据!Thread-2准备取数据!Thread-2已经取走数据,队列目前有2个数据Thread-0已经放了数据,队列目前有3个数据Thread-0准备放数据!Thread-2准备取数据!Thread-2已经取走数据,队列目前有2个数据Thread-1已经放了数据,队列目前有3个数据 */ final BlockingQueue queue = new ArrayBlockingQueue(3); for(int i=0;i<2;i++){ new Thread(){ public void run(){ while(true){ try { Thread.sleep((long)(Math.random()*1000)); System.out.println(Thread.currentThread().getName() + "准备放数据!"); queue.put(1); // 非原子性语句,可能不打印 System.out.println(Thread.currentThread().getName() + "已经放了数据," + "队列目前有" + queue.size() + "个数据"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } new Thread(){ public void run(){ while(true){ try { //将此处的睡眠时间分别改为100和1000,观察运行结果 Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "准备取数据!"); queue.take(); // 非原子性语句,可能不打印 System.out.println(Thread.currentThread().getName() + "已经取走数据," + "队列目前有" + queue.size() + "个数据"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }}
/** * 使用 阻塞队列 完成 _4_TraditionalThreadCommunication 案例 * * @author Wjz * */public class _22_BlockingQueueCommunication { public static void main(String[] args) { final Business business = new Business(); new Thread(new Runnable() { @Override public void run() { for (int i = 1; i <= 50; i++) { business.sub(i); } } }).start(); for (int i = 1; i <= 50; i++) { business.main(i); } } static class Business { BlockingQueue<Integer> queue1 = new ArrayBlockingQueue<Integer>(1);// 初始化为1 BlockingQueue<Integer> queue2 = new ArrayBlockingQueue<Integer>(1);// 初始化为1 // 匿名构造方法,优先于任意构造方法。每个构造方法初始化一次,匿名构造方法也跟着初始化 /*static 静态代码块,只在类初始化的时候执行一次*/ { try { queue2.put(1); } catch (InterruptedException e) { e.printStackTrace(); } } public void sub(int i) { try { queue1.put(1); } catch (InterruptedException e) { e.printStackTrace(); } for (int j = 1; j <= 10; j++) { System.out.println("sub thread sequece of " + j + ",loop of " + i); } try { queue2.take(); } catch (InterruptedException e) { e.printStackTrace(); } } public void main(int i) { try { queue2.put(1); } catch (InterruptedException e1) { e1.printStackTrace(); } for (int j = 1; j <= 100; j++) { System.out.println("main thread sequece of " + j + ",loop of " + i); } try { queue1.take(); } catch (InterruptedException e) { e.printStackTrace(); } } }}
Java 多线程 SynchronousQueue 阻塞同步队列
- 一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然。
- 同步队列没有任何内部容量,甚至连一个队列的容量都没有。
Java 多线程 集合并发操作的ConcurrentModificationException
public class _23_CollectionModifyException { public static void main(String[] args) { Collection users = // new CopyOnWriteArrayList(); new ArrayList(); users.add(new User("张三", 28)); users.add(new User("李四", 25)); users.add(new User("王五", 31)); Iterator itrUsers = users.iterator(); while (itrUsers.hasNext()) { System.out.println("aaaa"); User user = (User) itrUsers.next(); if ("王五".equals(user.getName())) { // 直接修改集合 会报错 users.remove(user); // 修改迭代器,正常 //itrUsers.remove(); } else { System.out.println(user); } } System.out.println("当前集合大小:"+users.size()); }}class User implements Cloneable { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof User)) { return false; } User user = (User) obj; // if(this.name==user.name && this.age==user.age) if (this.name.equals(user.name) && this.age == user.age) { return true; } else { return false; } } public int hashCode() { return name.hashCode() + age; } public String toString() { return "{name:'" + name + "',age:" + age + "}"; } public Object clone() { Object object = null; try { object = super.clone(); } catch (CloneNotSupportedException e) { } return object; } public void setAge(int age) { this.age = age; } public String getName() { return name; }}
阅读全文
0 0
- Java多线程与并发库高级应用
- Java多线程与并发库高级应用
- Java多线程与并发库高级应用
- Java多线程与并发库高级应用
- 视频专辑:张孝祥 Java多线程与并发库高级应用
- Java多线程与并发库高级应用之线程池
- Java多线程与并发库高级应用之信号量Semaphore
- Java多线程与线程并发库高级应用笔记
- Java多线程与并发库高级应用之线程池
- Java多线程与并发库高级应用05
- Java多线程与并发库高级应用架构
- 多线程与并发库高级应用
- 多线程与并发库高级应用
- Java多线程与并发库高级应用以及设计模式的实战应用
- 黑马程序员——Java多线程与线程并发库高级应用笔记
- Java多线程与并发库高级应用之Callable和Future
- Java多线程与并发库高级应用之读写锁ReadWriteLock
- Java多线程与并发库高级应用之公共屏障点CyclicBarrier
- [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
- python打开网页获取网页内容方法总结
- JDBC常用的类和接口
- 单独将ajax请求放入js文件中URL问题
- HBase(0.96以上版本)过滤器Filter详解及实例代码(转)
- Java多线程与并发库高级应用
- spin_lock & mutex_lock的区别? .
- 持续集成入门
- 禅道的最简使用
- NYOJ【463】九九乘法表【循环】
- 用CSS写一个简单的幻灯片效果页面
- sklearn编程模型
- 机器学习实战第二章kNN算法详解
- Linux电源管理(9)_wakelocks