1.确保提交到线程池的任务可中断

原文:www.securecoding.cert.org,TPS02-J. Ensure thattasks submitted to a thread pool are interruptible。

为了能完全关闭线程池或者取消线程池中的个别任务,程序应提交支持使用Thread.interrupt()中断的任务到线程池。程序不应提交不支持中断的任务到线程池,除非是无阻塞且短时间运行的任务。

根据java.util.concurrent.ExecutorService.shutdownNow() Java API的描述:

尝试终止所有正在执行的任务,停止所有等待处理的任务,并且返回等待执行的任务列表…

除了尽最大努力尝试终止正在执行的任务之外,没有任何其他的保证。例如,典型实现是通过Thread.interrupt()进行取消,因此任何不能中断的任务可能永远不会被终止。

违规代码示例(Shutting Down Thread Pools)

如下是违规代码示例,提交SocketReader任务到PoolService声明的线程池中:

因为任务不支持Thread.interrupt()进行中断,且因为shutdown()方法必须等到所有正执行的任务执行完成,所以shutdownNow()方法可能不能立即完全关闭线程池。

同样,某些不用Thread.interrupted() 而使用其他的机制来决定何时关闭的任务,其是无法响应shutdown()和shutdownNow()。例如,通过检查一个volatile标志位来决定是否可安全关闭的任务,对这些方法是无法响应的。THI05-J. Do not use Thread.stop() to terminate threads提供了使用标志位终止线程的更多信息。

合规解决方案(Submit InterruptibleTasks)

如下合规解决方案定义了SocketReader的一个可中断的版本,实例化并提交到线程池:

2.持有锁时不要执行阻塞操作

原文:www.securecoding.cert.org,LCK09-J.Do not perform operations that canblock while holding a lock。

持有锁时执行耗时或阻塞操作会严重降低系统性能,且可能导致饥饿。此外,死锁会导致相互依赖的线程无限阻塞。阻塞操作包括网络、文件、控制台I/O(如Console.readLine())和对象序列化,无限延迟线程执行也算是一种阻塞操作(如通过Thread.sleep())。因此,在持有锁时,程序不应该执行阻塞操作。

当Java虚拟机(JVM)与不可靠网络、文件I/O交互时,可能引起巨大的性能损耗。在这种情况下,应避免持有锁时执行网络上的文件I/O操作。在等待输出流锁或I/O完成事件的文件操作(如日志)会阻塞,可以在一个单独的线程中执行来加速任务处理。记录请求日志可以添加到一个队列,与直接文件I/O相比,队列put()操作会增加一点小的开销。

违规代码示例(Deferring a Thread)

如下违规代码示例定义了一个接受timeout参数的工具类:

方法是synchronized,当线程休眠后其他线程不能使用synchronized的方法。当前对象的监视器并未被释放,这是因为Thread.sleep() 方法没有同步语义。

合规解决方案(Intrinsic Lock)

如下合规解决方案定义了doSomething()方法,其带有一个timeout参数而不是time参数。使用Object.wait()代替Thread.sleep(),Object.wait()允许设置一个通知的超时周期,超时后可以唤醒线程。

进入到等待状态后当前对象的监视器会立即释放。当超时后,线程会在重新获取到当前对象的监视器后恢复继续执行。

根据Object类Java API的描述:

wait方法,它将当前线程放入到该对象的等待集,且只有该对象能释放锁;当线程等待时,当前线程上的任何synchronized的其他对象将保持锁定。

此方法应仅由该对象监视器拥有者线程调用。

程序必须确保持有其他对象锁的线程在进入等待状态之前适时释放这些锁。等待和通知的一些额外帮助可见 THI03-J. Always invoke wait() and await() methods insidea loop 和 THI02-J. Notify all waiting threads rather than a single thread。

违规代码示例(Network I/O)

如下违规代码示例定义了sendPage()方法,其从服务端向客户端发送一个Page对象。该方法是synchronized,在多线程请求并发访问时来来保护 pageBuff数组。

public class SendPage {

private final int MAX_PAGE_SIZE = 10;

Page[] pageBuff = new Page[MAX_PAGE_SIZE];

public class Page {

int code;

String message;

Object page;

String pageName;

public String getName() {

// TODO Auto-generated method stub

return pageName;

}

}

public synchronized boolean sendPage(Socket socket, String pageName) throws IOException {

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

Page targetPage = null;

for (Page page : pageBuff) {

if (page.getName().compareTo(pageName) == 0) {

targetPage = page;

}

}

if (targetPage == null) {

return false;

}

out.writeObject(targetPage);

out.flush();

out.close();

return true;

}

}

在synchronized的sendPage()方法中调用writeObject()会造成延迟和死锁,像在高延迟网络或当网络连接有损(丢包)情况时。

合规解决方案

如下合规解决方案将整个过程拆分为如下步骤:

1.在数据结构上执行的操作需要同步;

2.创建对象的副本用于发送;

3.在单独的无同步方法中执行网络调用。

public class SendPageCanStop {

private final int MAX_PAGE_SIZE = 10;

Page[] pageBuff = new Page[MAX_PAGE_SIZE];

public class Page {

int code;

String message;

Object page;

String pageName;

public String getName() {

// TODO Auto-generated method stub

return pageName;

}

}

public boolean sendPage(Socket socket, String pageName) throws IOException {

Page targetPage = getPage(pageName);

if (targetPage == null) {

return false;

}

return deliverPage(socket, targetPage);

}

private synchronized Page getPage(String pageName) {

Page targetPage = null;

for (Page p : pageBuff) {

if (p.getName().compareTo(pageName) == 0) {

targetPage = p;

}

}

return targetPage;

}

private boolean deliverPage(Socket socket, Page page) {

ObjectOutputStream out = null;

boolean result = true;

try {

out = new ObjectOutputStream(socket.getOutputStream());

out.writeObject(page);

out.flush();

out.close();

} catch (Exception e) {

result = false;

} finally {

try {

if (out != null) {

out.close();

}

} catch (Exception e2) {

result = false;

}

}

return result;

}

在该合规解决方案中,无同步的sendPage()方法调用同步的getPage()方法从pageBuff 数组获取请求的Page。在Page取出后,sendPage()调用无同步的deliverPage()方法将Page交付给客户端。

java 中断代码_你的java代码可中断吗?(2)相关推荐

  1. java在线编辑器_微软开源在线代码编辑器——Monaco Editor

    介绍 Monaco Editor是为VS Code提供支持的代码编辑器,运行在浏览器环境中.编辑器提供代码提示,智能建议等功能.供开发人员远程更方便的编写代码.移动浏览器或移动Web框架不支持Mona ...

  2. Java函数编码_转[收集java的常用函数代码]

    转[收集java的常用函数代码] package net.java2000.tools; /** * Title:        Java Bean 工具 * Description: * Copyr ...

  3. java jar 打印_三种Java打印PDF文档的实例代码

    以下内容归纳了通过Java程序打印PDF文档时的3种情形.即: 1 静默打印 2 显示打印对话框打印 3 打印PDF时自定义纸张大小 使用工具:Spire.PDF for Java Jar文件获取及导 ...

  4. 红牛农场java代码_实验题目 Java语言概述.doc

    实验题目 Java语言概述 实验一 Java语言概述 [实验目的] 1.掌握开发Java应用程序的三个步骤:编写源文件.编译源文件和运行应用程序. 2.熟悉Java应用程序的基本结构,并能联合编译应用 ...

  5. java设计缺陷_多个常见代码设计缺陷

    0.前言 在软件设计开发中,代码的设计都体现在:子系统与子系统.模块与模块.函数与函数之间的关系,设计越糟糕的软件,维护成本越高,质量也往往难以达标和称赞. 好的设计必定是:层次关系简洁.清晰.易维护 ...

  6. java 异常机制_深入理解Java异常处理机制

    一.引子 try-catch-finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解.不过,我亲自体验的"教训"告诉我,这个东西可不是想象中 ...

  7. java 事件通知_正确获取Java事件通知

    java 事件通知 实现观察者模式以提供Java事件通知似乎是一件容易的事. 但是,容易陷入一些陷阱. 这是我在各种场合不慎造成的常见错误的解释-- Java事件通知 让我们从一个简单的bean St ...

  8. 什么样的代码是好代码_什么是好代码?

    什么样的代码是好代码 编码最佳实践 (Coding Best-Practices) In the following section, I will introduce the topic at ha ...

  9. python 代码_如何让Python代码加速运行?

    Python 是一种脚本语言,相比 C/C++ 这样的编译语言,在效率和性能方面存在一些不足.但是,有很多时候,Python 的效率并没有想象中的那么夸张.本文对一些 Python 代码加速运行的技巧 ...

  10. 马士兵 java 学习笔记_马士兵java教程笔记1

    ---恢复内容开始--- 前记 虽然已经是个研究生了,但是会的东西还是特别的少 甚至连java都不能说是很会 所以准备从现在开始能好好的学习java 变成java master 标识符 标识符是由字母 ...

最新文章

  1. CentOS 7.5 如何升级Git实录
  2. java十六进制转二进制_Java进制都有哪些?
  3. 深入理解Golang 编程思维和工程实战
  4. batch-size 深度学习笔记
  5. 蔡高厅老师 - 高等数学阅读笔记 - 03 - 极限(13、14、15、16、17)
  6. Android 功耗(10)---如何测试 Mediatek 平台各个场景的功耗数据?
  7. Python socket – network programming tutorial
  8. 工具开发:勿以善小而不为
  9. Ubuntu16.04下Nvidia+Cuda8.0+Dynet安装教程
  10. 【modelarts】华为人工智能平台_modelarts平台系列教程1
  11. 计算机设置鼠标关灯,老司机详解罗技鼠标怎样关闭灯光
  12. 西门子触摸屏脚本程序_西门子PLC触摸屏如何编写程序
  13. 电子设计大赛-室内可见光定位装置
  14. love2d 编译 android,Love2D游戏脚本在windows平台下打包exe发布教程
  15. 什么是法?什么是僧?
  16. 室友利用一把王者的时间就学会了【C语言结构体内存对齐】
  17. DKN: Deep Knowledge-Aware Network for News Recommendation
  18. android 小视频 应用,短视频应用专题 - 只给你好看的短视频合集 - Android 应用 - 【最美应用】...
  19. 推荐一个下载神器(官网资料下载必备)
  20. 加快发展职业教育 让每个人都有人生出彩机会

热门文章

  1. 滤波器开发之四:基于算术平均的中值滤波器
  2. 初探Backbone
  3. 现代软件工程 结对编程 (II) 电梯调度
  4. 敏捷软件开发宣言–Manifesto for Agile Software Development
  5. 预充电电路工作原理_LED触摸调光台灯控制电路板的工作原理
  6. html表单传值,如何将用户输入的表单值从html传递给javascript?
  7. u盘启动蓝屏 索尼vaio_U盘重装系统出现蓝屏?不要急,这四个手段轻松帮你解决!...
  8. mysql存储过程注释方法_mysql存储过程 详细注释
  9. 使用sqlserver连接mysql服务_Sqlserver创建连接MySql的链接服务器
  10. 计量经济学计算机输出结果,计量经济学作业答案A..doc