首页 > 编程语言 > Java编程思想19

Java编程思想19

时间:2022-12-26 10:55:05浏览次数:42  
标签:Java generator 19 编程 int 任务 test public IntGenerator

共享受限资源

1. 不正确访问资源

  考虑下面的例子,其中一个任务产生产生偶数,而其他任务消费这些数字。而这些消费者任务的唯一工作就是校验偶数的有效性

package concurrency;

/**
* @author Mr.Sun
* @date 2022年09月03日 21:49
*
* <p>
* 创建一个名为IntGenerator的抽象类,它包含EventChecker必须了解的必不可少的方法,即一个next()方法,和一个可以执行撤销的方法
* </p>
*/
public abstract class IntGenerator {

private volatile boolean canceled = false;
public abstract int next();

/**
* 修改canceled标志的状态
*/
public void cancel() {
canceled = true;
}

/**
* 查看该对象是否已被撤销
*/
public boolean isCanceled() {
return canceled;
}

}

 任何IntGenerator 都可以使用下面的EventChecker类来测试:

package concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* @author Mr.Sun
* @date 2022年09月03日 21:52
*
* 校验偶数的有效性
*/
public class EventChecker implements Runnable {

private IntGenerator generator;
private final int id;

public EventChecker(IntGenerator generator, int id) {
this.generator = generator;
this.id = id;
}

@Override
public void run() {
while (!generator.isCanceled()) {
int val = generator.next();
if (val % 2 != 0) {
System.out.println(val + " not event");
// 取消 事件检查
generator.cancel();
}
}
}

public static void test(IntGenerator gp, int count) {
System.out.println("按 Ctrl + C 退出");
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < count; i++) {
exec.execute(new EventChecker(gp, i));
}
exec.shutdown();
}

public static void test(IntGenerator gp) {
// count 默认值
test(gp, 10);
}
}

 

注意,在本例中可以被撤销的类不是Runnable,而所有依赖于IntGenerator对象的EvenChecker任务将测试它,以查看它是否已经被撤销,正如你在run()中所见。通过这种方式,共享公共资源(IntGenerator)的任务可以观察该资源的终止信号。这可以消除所谓竞争条件,即两个或更多的任务竞争响应某个条件,因此产生冲突或不一致结果的情况。你必须仔细考虑并防范并发系统失败的所有可能途径,例如,一个任务不能依赖于另一个任务,因为任务关闭的顺序无法得到保证。这里,通过使任务依赖于非任务对象,我们可以消除潜在的竞争条件。
  test()方法通过启动大量使用相同的IntGenerator的EvenChecker,设置并执行对任何类型的IntGenerator的测试。如果IntGenerator引发失败,那么test()将报告它并返回,否则,你必须按下Ctrl-C来终止它。
  我们看到的第一个IntGenerator有一个可以产生一系列数值的next():

package concurrency;

/**
* @author Mr.Sun
* @date 2022年09月03日 22:02
*/
public class EventGenerator extends IntGenerator {

private int currentEventVal = 0;

@Override
public int next() {
++currentEventVal;
// 可能出现资源竞争问题的地方
++currentEventVal;
return currentEventVal;
}

public static void main(String[] args) {
EventChecker.test(new EventGenerator());
}
}

 

一个任务有可能在另一个任务执行第一个对currentEvenValue的递增操作之后,但是没有执行第二个操作之前,调用next()方法。这将使这个值处于“不恰当”的状态。为了证明这是可能发生的,EvenChecker.test()创建了一组EvenChecker对象,以连续地读取并输出同一个EvenGenerator,并测试检查每个数值是否都是偶数。如果不是,就会报告错误,而程序也将关闭。
  有一点很重要,那就是要注意到递增程序自身也需要多个步骤,并且在递增过程中任务可能会被线程机制挂起——也就是说,在Java中,递增不是原子性的操作。因此,如果不保护任务,即使单一的递增也不是安全的。

标签:Java,generator,19,编程,int,任务,test,public,IntGenerator
From: https://www.cnblogs.com/LvJinshuai/p/17005222.html

相关文章

  • 实现JNI的另一种方法:使用RegisterNatives方法传递和使用Java自定义类
    除了使用传统方法实现JNI外,也可以使用RegisterNatives实现JNI。和传统方法相比,使用RegisterNatives的好处有三点:1、C++中函数命名自由,不必像javah自动生成的函数声明那样,拘......
  • 【HMS Core】升级SDK报错app_id failed: java.io.FileNotFoundException: agconnect-s
    问题描述:升级推送服务最新版SDK报错app_idfailed:java.io.FileNotFoundException:agconnect-services.json问题分析:从日志来看,是没有找到agconnect-services.json文件。......
  • Java小白必会!Intellij IDEA安装、配置及使用详细教程
    一.前言所谓工欲善其事必先利其器,一个好的工具对工作效率的提升是有非常大的帮助的。而在咱们程序员开发时,一个好的集成开发工具对于提高我们的编码效率和编程体验来说也是......
  • Java版小米商城项目简介
    小米商城课程详情1.课程介绍本套课程主要是基于Servlet、HTML、JS、Ajax、JSP、MySQL、JDBC、Tomcat、微信支付等web技术,仿照小米商城来实现一个电子商城项目。注意:本课程配......
  • 1:Web开发入门-Java Web
    (目录)1.1什么是Web应用程序在Sun的JavaServlet规范中,对JavaWeb应用作了这样定义:“JavaWeb应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在......
  • java的异常体系图
    本文主要讲述java的异常体系图老韩图解:  自己理解: ......
  • 上周热点回顾(12.19-12.25)
    热点随笔:· 用Echarts实现前端表格引用从属关系可视化 (葡萄城技术团队)· 工作5年的老程序员的年终总结 (逆袭之路666)· 我的2022年-总结、感悟、碎碎念 (XSpring......
  • JavaVM & JNIEnv
    JNIEnv提供了大多数的JNI函数。你的本地方法都会接收JNIEnv作为第一个参数。JNIEnv用于本地线程存储。因此,你不能在线程间共享同一个JNIEnv。如果一个代码段没有其他方式获......
  • 【HMS Core】升级SDK报错app_id failed: java.io.FileNotFoundException: agconnect-s
    ​问题描述:升级推送服务最新版SDK报错app_idfailed:java.io.FileNotFoundException:agconnect-services.json 问题分析:从日志来看,是没有找到agconnect-services.js......
  • 第一个Java程序——Hello World
    环境:记事本、DOS窗口步骤:编写代码文件,后缀改为java打开DOS窗口找到代码存放位置使用 javacHelloWorld.java进行编译使用javaHelloWorld 执行代码:1p......