- 浏览: 183400 次
- 性别:
- 来自: 杭州
博客专栏
-
Java技术分享
浏览量:0
文章分类
最新评论
-
masuweng:
学习了,学习了
mybatis是如何防止SQL注入的 -
somefuture:
终于知道了#$的区别
mybatis是如何防止SQL注入的 -
masuweng:
...
tomct处理请求的流程 -
zhp8341:
masuweng 写道寻求cas的更多例子, http://w ...
JUC之CAS -
臻是二哥:
java.util.concurrent包中到处都使用了CAS ...
JUC之CAS
中断处理
在java程序中,当使用Thread.sleep()或者BlockingQueue.take()等阻塞方法时,需要处理InterruptedException。对于这种异常,通常有2种方案进行处理。
1. 传递异常:将异常传递给方法的调用者。示例如下:
2. 恢复异常:在大多数情况下,异常是可以传递的,但有些情况是无法传递异常的,比如在Runnable的run()方法中,我们不可以抛出异常。此时需要我们恢复异常,这样在调用栈中更高层次的代码将看到引发了一个中断。示例如下:
以上是处理InterruptedException的常用方法,对于InterruptedException,千万不要捕获异常但不做任何处理。当我们使用中断来结束线程时,在catch块中也可以使用interrupted()来清除异常。
任务取消
多线程编程时,有时候需要取消某些任务线程,有以下3种方案:
1. 设定一个线程取消的标记,任务线程定期的检查这个标记。示例如下:
当while(!cancel)循环中调用了一个阻塞的方法时,使用标记位的方式终止程序就不再使用了,此时使用中断的方式退出程序:
3. 在生产者消费者问题中,使用“毒丸对象”来终止消费者线程。
在java程序中,当使用Thread.sleep()或者BlockingQueue.take()等阻塞方法时,需要处理InterruptedException。对于这种异常,通常有2种方案进行处理。
1. 传递异常:将异常传递给方法的调用者。示例如下:
BlockingQueue<String> queue; public String getNextString() throws InterruptedException{ return queue.take(); }
2. 恢复异常:在大多数情况下,异常是可以传递的,但有些情况是无法传递异常的,比如在Runnable的run()方法中,我们不可以抛出异常。此时需要我们恢复异常,这样在调用栈中更高层次的代码将看到引发了一个中断。示例如下:
BlockingQueue<String> queue; public String getNextString() throws InterruptedException{ String result=null; try{ result=queue.take(); }catch(InterruptedException e){ Thead.currentThread.interrupt(); }finally{ Return result; } }
以上是处理InterruptedException的常用方法,对于InterruptedException,千万不要捕获异常但不做任何处理。当我们使用中断来结束线程时,在catch块中也可以使用interrupted()来清除异常。
任务取消
多线程编程时,有时候需要取消某些任务线程,有以下3种方案:
1. 设定一个线程取消的标记,任务线程定期的检查这个标记。示例如下:
class Task implements Runnable{ private volatile boolean cancel=false; @Override public void run() { while(!cancel){ System.out.println("..."); } } public void cancel(){ cancel=true; } }2. 上面的示例描述的是最一般的场景,试想一下,如果while(!cancel)循环中调用了一个阻塞的方法,那么有这样一种可能:程序可能阻塞在某个方法中。示例如下:
class Task implements Runnable{ private volatile boolean cancel=false; private BlockingQueue<String> blockingQueue; public Task(BlockingQueue<String> queue){ this.blockingQueue=queue; } @Override public void run() { try{ while(!cancel){ System.out.println("..."); this.blockingQueue.take();//当程序阻塞在此处时,即便cancel被更新了,也无法感知,这种情况下,程序永远无法退出。 } }catch(InterruptedException e){ Thread.currentThread().interrupt(); } } public void cancel(){ cancel=true; } }
当while(!cancel)循环中调用了一个阻塞的方法时,使用标记位的方式终止程序就不再使用了,此时使用中断的方式退出程序:
import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class CDemo { public static void main(String [] args) throws Exception{ BlockingQueue<String> b=new ArrayBlockingQueue<String>(3); b.put("a"); b.put("ab"); b.put("abc"); Task task=new Task(b); task.start(); Thread.sleep(4000); task.cancel(); } } class Task extends Thread{ private BlockingQueue<String> blockingQueue; public Task(BlockingQueue<String> queue){ this.blockingQueue=queue; } @Override public void run() { try{ while(true){ // if(Thread.currentThread().isInterrupted()) //一定注意,这行是错误做法 if(interrupted())//判断当前线程是否被中断 break; String str=this.blockingQueue.take(); System.out.println(str); } }catch(InterruptedException e){ //Thread.currentThread().interrupt(); interrupted();//清除中断痕迹 }finally{ System.out.println("线程结束!"); } } public void cancel(){ this.interrupt();//中断当前线程 // Thread.currentThread().interrupt(); //一定注意,这行是错误做法 } }
3. 在生产者消费者问题中,使用“毒丸对象”来终止消费者线程。
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; public class Coordinator { public static final Object POISON_PILL = new Object();//special object to kill consumers private int productCount = 1; private int consumerCount = 3; public void startAll() throws Exception{ BlockingQueue<Object> queue = new ArrayBlockingQueue<Object>(5); CountDownLatch activeProductorNum = new CountDownLatch(productCount); CountDownLatch activeConsumerNum = new CountDownLatch(consumerCount); for(int i = 0; i < consumerCount; i++){ new Thread(new Consumer("consumer " + i, queue,activeConsumerNum)).start(); } for(int i = 0; i < productCount; i++){ new Thread(new Producer("producer " + i, queue, activeProductorNum)).start(); } activeProductorNum.await();//等待所有生产者生产结束 System.out.println("All producer finished, putting POISON_PILL to the queue to stop consumers!"); queue.put(POISON_PILL); activeConsumerNum.await();//等待所有生产者生产结束 System.out.println("All consumer finished!"); } public static void main(String[] args) throws Exception{ new Coordinator().startAll(); } } class Producer implements Runnable { private String name; private BlockingQueue<Object> queue; private CountDownLatch activeProducerNum; public Producer(String name, BlockingQueue<Object> queue, CountDownLatch activeProducerNum){ this.name = name; this.queue = queue; this.activeProducerNum=activeProducerNum; } @Override public void run() { try { for(int i=0;i<10;i++){ queue.put(i); System.out.println(name + " produced "+i); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally{ System.out.println(name + " finished."); activeProducerNum.countDown(); } } } class Consumer implements Runnable { private String name; private BlockingQueue<Object> queue; private CountDownLatch activeConsumerNum; public Consumer(String name, BlockingQueue<Object> queue,CountDownLatch activeConsumerNum){ this.name = name; this.queue = queue; this.activeConsumerNum=activeConsumerNum; } @Override public void run() { try { while (true) { Object item = queue.take(); if (item == Coordinator.POISON_PILL) { queue.put(item);//放回继续毒害其他消费者 break; } System.out.println(name + " consumed "+item); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally{ System.out.println(name + " finished"); activeConsumerNum.countDown(); } } }
发表评论
-
精心准备的讲解Java多线程的知乎Live
2018-09-02 21:39 704花了一个月的时间,结合自己的理解,制作了一个以图片的方式讲解J ... -
在知乎推出Java求职类专栏文章
2018-08-27 12:06 790从昨天起,笔者开始在知乎推出Java求职类专栏文章,主要涉及一 ... -
JUC之AQS
2016-07-27 15:49 1205AQS是同步框架,它进行 ... -
JUC之CAS
2016-07-27 10:56 1557JUC是java.util.concurrent包 ... -
JAVA并发-线程状态和线程组
2016-07-18 14:14 1267在Java中,线程有6种基本状态,理解这6种基本状态之间的关系 ... -
JAVA并发-条件队列
2016-07-02 09:57 1115在JVM系列博客http://yizhen ... -
JAVA并发-显式锁(二)
2016-06-06 09:25 1024在上一篇博客《JAVA并发-显式锁(一)》中介绍了Lock和R ... -
JAVA并发-显式锁(一)
2016-06-05 20:40 891JAVA语言除了提供内置锁synchronized,还在JDK ... -
JAVA并发-减少锁的竞争
2016-06-04 16:01 1847降低锁的竞争可以提高 ... -
JAVA并发-3种典型的死锁
2016-06-03 19:54 1621在JAVA并发编程中,我们 ... -
JAVA并发-3种典型的死锁
2016-06-03 10:02 10在JAVA并发编程中,我们 ... -
JAVA并发-ThreadPoolExecutor线程池的使用
2016-05-30 16:19 2356在博客JAVA并发-Executor任务执行框架中曾说过,Ex ... -
JAVA并发-Executor任务执行框架
2016-05-27 19:10 432首先介绍两个重要的接 ... -
JAVA并发-DCL与JMM
2016-04-26 19:21 1568首先必须声明,在volatil ... -
JAVA并发- 典型连接池的实现
2016-04-22 10:44 1135package com.xyz.connpool; pu ... -
JAVA并发-构建可靠的结果缓存
2016-04-10 16:58 55在学习了前面关于多线程的博客之后,下面来介绍一个构建可靠结果缓 ... -
JAVA并发-并发编程常用类
2016-04-08 11:07 991在讲同步工具类之前,笔者想先介绍一下Runnable,Call ... -
JAVA并发-同步容器和并发容器
2016-04-07 19:02 698常见的同步容器类包括V ... -
JAVA并发-开发线程安全类
2016-04-01 10:23 840我们知道,面向对象的 ... -
JAVA并发-为现有的线程安全类添加原子方法
2016-03-30 20:46 1390JAVA中有许多线程安全的基础模块类,一般情况下,这些基础模块 ...
相关推荐
1.2.3 异步事件的简化处理 1.2.4 响应更灵敏的用户界面 1.3 线程带来的风险 1.3.1 安全性问题 1.3.2 活跃性问题 1.3.3 性能问题 1.4 线程无处不在 第一部分 基础知识 第2章 线程安全性 2.1 什么是线程安全...
7.1 任务取消 7.2 停止基于线程的服务 7.3 处理反常的线程终止 7.4 JVM关闭 第8章 应用线程池 8.1 任务与执行策略问的隐性耦合 8.2 定制线程池的大小 8.3 配置ThreadPoolExecutor 8.4 扩展ThreadPoolExecutor 8.5 ...
1.2.3 异步事件的简化处理 1.2.4 响应更灵敏的用户界面 1.3 线程带来的风险 1.3.1 安全性问题 1.3.2 活跃性问题 1.3.3 性能问题 1.4 线程无处不在 第一部分 基础知识 第2章 线程安全性 2.1 什么是线程安全...
7.1 任务取消 7.2 停止基于线程的服务 7.3 处理反常的线程终止 7.4 jvm关闭 第8章 应用线程池 8.1 任务与执行策略问的隐性耦合 8.2 定制线程池的大小 8.3 配置threadpoolexecutor 8.4 扩展threadpoolexecutor 8.5 ...
java7在并发编程方面,带来了很多令人激动的新功能,这将使你的应用程序具备更好的并行任务性能。 《Java 7并发编程实战手册》是Java 7并发编程的实战指南,介绍了Java 7并发API中大部分重要而有用的机制。全书分为9...
任务取消 停止基于线程的服务 处理非正常的线程终止 JVM关闭 线程池的定制化使用 任务和执行策略之间的隐性耦合 线程池的大小 配置ThreadPoolExecutor(自定义的线程池) 此处需要注意...
中文完整版的Java并发编程实践PDF电子书 作者:Brian Gogetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea 译者:韩锴 方秒 目录 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 ...
中文完整版的Java并发编程实践PDF电子书 作者:Brian Gogetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea 译者:韩锴 方秒 目录 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 ...
详细介绍java并发编程相关知识: 基础知识 并发与并行 Java并发演进历史 Java并发模型 线程模型 存储模型 JVM同步原语 volatile CAS ... 保护“共享数据” ... 线程的中断与任务的取消 其他
可定义等待队列满载后处理新请求的策略:抛弃队列中最新的任务抛弃队列中最旧的任务抛弃当前新任务直接执行(阻塞当前线程)抛出异常(中断当前线程)LiteGo 使用初始化:// 智能并发调度控制器:设置[最大并发数]...
27.4 取消任务和处理异常 578 27.4.1 协作式取消的原理 578 27.4.2 使用aggregateexception类处理任务异常 586 27.4.3 为canceled和faulted任务使用延续任务 589 第27章快速参考 590 第28章 执行并行数据访问 ...
最初是Windows NT版本的可选包,随后内置在Windows 2000、Windows XP Professional和Windows Server 2003一起发行,但在普遍使用的Windows XP Home版本上并没有IIS。 添加和运行准备 一、IIS的添加 请进入“控制...
第16章 多线程——Java中的并发协作 343 16.1 线程的基本知识 343 16.1.1 多线程编程的意义 343 16.1.2 定义自己的线程 344 16.1.3 创建线程对象 345 16.1.4 启动线程 347 16.1.5 同时使用多个线程 ...