Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java发生-在两个ConcurrentMaps上一致的线程视图之前

Java发生-在两个ConcurrentMaps上一致的线程视图之前
EN

Stack Overflow用户
提问于 2015-11-05 13:56:07
回答 2查看 159关注 0票数 1

我有一个java类来处理多线程订阅服务。通过实现可订阅接口,可以将任务提交给服务并定期执行。下面是代码的草图:

代码语言:javascript
运行
AI代码解释
复制
import java.util.concurrent.*;

public class Subscribtions {

    private ConcurrentMap<Subscribable, Future<?>> futures = new ConcurrentHashMap<Subscribable, Future<?>>();
    private ConcurrentMap<Subscribable, Integer> cacheFutures = new ConcurrentHashMap<Subscribable, Integer>();
    private ScheduledExecutorService threads;

    public Subscribtions() {
        threads = Executors.newScheduledThreadPool(16);
    }

    public void subscribe(Subscribable subscription) {
        Runnable runnable = getThread(subscription);
        Future<?> future = threads.scheduleAtFixedRate(runnable, subscription.getInitialDelay(), subscription.getPeriod(), TimeUnit.SECONDS);
        futures.put(subscription, future);
    }

    /*
     * Only called from controller thread
     */
    public void unsubscribe(Subscribable subscription) {
        Future<?> future = futures.remove(subscription);    //1. Might be removed by worker thread 
        if (future != null)
            future.cancel(false);
        else {
            //3. Worker-thread view     := cacheFutures.put() -> futures.remove()
            //4. Controller-thread has seen futures.remove(), but has it seen cacheFutures.put()?
        }
    }

    /*
     * Only called from worker threads
     */
    private void delay(Runnable runnable, Subscribable subscription, long delay) {
        cacheFutures.put(subscription, 0);                  //2. Which is why it is cached first
        Future<?> currentFuture = futures.remove(subscription);
        if (currentFuture != null) {
            currentFuture.cancel(false);
            Future<?> future = threads.scheduleAtFixedRate(runnable, delay, subscription.getPeriod(), TimeUnit.SECONDS);
            futures.put(subscription, future);
        }
    }

    private Runnable getThread(Subscribable subscription) {
        return new Runnable() {
            public void run() {
                //Do work...
                boolean someCondition = true;
                long someDelay = 100;
                if (someCondition) {
                    delay(this, subscription, someDelay);
                }
            }
        };
    }

    public interface Subscribable {
        long getInitialDelay();
        long getPeriod();
    }
}

因此,该课程允许:

  • 订阅新任务
  • 取消订阅现有任务
  • 延迟周期性执行的任务

订阅由外部控制线程添加/删除,但延迟仅由内部工作线程引起。例如,如果工作线程没有从上次执行中找到更新,或者例如,如果线程只需要在00.00 - 23.00之间执行,则可能发生这种情况。

我的问题是,一个工作线程可以调用delay()并从ConcurrentMap中删除它的未来,而控制器线程可以同时调用unsubscribe()。然后,如果控制器线程在工作线程进入新的未来之前检查ConcurrentMap,则unsubscribe()调用将丢失。

有一些(也许不是详尽无遗的)解决方案:

  • 使用delay()unsubscribe()方法之间的锁
  • 和上面一样,但是每次订阅一个锁。
  • (首选?)不使用锁,但在delay()方法中使用“缓存”删除期货

至于第三种解决方案,由于工作线程已经建立了在关系cacheFutures.put() -> futures.remove()之前发生的事件,而ConcurrentMap的原子性使控制器线程看到了futures.remove(),那么它是否也看到了与工作线程相同的关系?即cacheFutures.put() -> futures.remove()?或者原子性只适用于稍后传播到其他变量的更新的futures映射吗?

任何其他评论也是欢迎的,尤指。考虑使用易失性关键字。是否应该声明缓存映射是不稳定的?谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-05 14:43:26

每次订阅一个锁将要求您维护另一个映射,并可能因此引入额外的并发问题。我认为最好避免这样做。同样的情况也适用于缓存已删除的订阅,另外,这也增加了不必要的资源保留的风险(请注意,您需要缓存的不是Future本身,而是与它们关联的Subscribable)。

无论如何,您都需要某种同步/锁定。例如,在您的选项(3)中,您需要避免对给定订阅在delay()缓存订阅和删除订阅Future之间发生delay()。在没有某种形式的锁定的情况下,避免这种情况的唯一方法是,每个订阅只使用一个Future,从subscribe()注册时一直保持到unsubscribe()删除为止。这样做不符合延迟预定订阅的能力。

至于第三种解决方案,由于工作线程已经建立了在关系cacheFutures.put() -> futures.remove()之前发生的事件,而ConcurrentMap的原子性使控制器线程看到futures.remove(),那么它是否也看到了与工作线程之前的关系相同的情况?

发生--以前是程序执行过程中动作之间的关系。它不特定于任何一个线程对执行的视图。

或者原子性只适用于期货地图,其他变量的更新将在以后传播?

控制器线程将始终在同一调用执行的cacheFutures.put()之前看到delay()调用所执行的futures.remove()。不过,我觉得这帮不了你。

是否应该声明缓存映射是不稳定的?

不是的。这没有任何用处,因为尽管映射的内容发生了变化,但映射本身始终是相同的对象,而且对它的引用不会改变。

您可以考虑让subscribe()delay()unsubscribe()分别在Subscribable上同步。这并不是我所理解的每个订阅都有一个锁的意思,但这是相似的。这将避免需要单独的数据结构来维护这些锁。如果您希望避免显式同步,也可以将锁定方法构建到Subscribable接口中。

票数 0
EN

Stack Overflow用户

发布于 2015-11-05 17:23:48

您有一个ConcurrentMap,但您没有使用它。考虑一下以下几点:

代码语言:javascript
运行
AI代码解释
复制
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

final class SO33555545
{

  public static void main(String... argv)
    throws InterruptedException
  {
    ScheduledExecutorService workers = Executors.newScheduledThreadPool(16);
    Subscriptions sub = new Subscriptions(workers);
    sub.subscribe(() -> System.out.println("Message received: A"));
    sub.subscribe(() -> System.out.println("Message received: B"));
    Thread.sleep(TimeUnit.SECONDS.toMillis(30));
    workers.shutdown();
  }

}

final class Subscriptions
{

  private final ConcurrentMap<Subscribable, Task> tasks = new ConcurrentHashMap<>();

  private final ScheduledExecutorService workers;

  public Subscriptions(ScheduledExecutorService workers)
  {
    this.workers = workers;
  }

  void subscribe(Subscribable sub)
  {
    Task task = new Task(sub);
    Task current = tasks.putIfAbsent(sub, task);
    if (current != null)
      throw new IllegalStateException("Already subscribed");
    task.activate();
  }

  private Future<?> schedule(Subscribable sub)
  {
    Runnable task = () -> {
      sub.invoke();
      if (Math.random() < 0.25) {
        System.out.println("Delaying...");
        delay(sub, 5);
      }
    };
    return workers.scheduleAtFixedRate(task, sub.getPeriod(), sub.getPeriod(), TimeUnit.SECONDS);
  }

  void unsubscribe(Subscribable sub)
  {
    Task task = tasks.remove(sub);
    if (task != null)
      task.cancel();
  }

  private void delay(Subscribable sub, long delay)
  {
    Task task = new Task(sub);
    Task obsolete = tasks.replace(sub, task);
    if (obsolete != null) {
      obsolete.cancel();
      task.activate();
    }
  }

  private final class Task
  {

    private final FutureTask<Future<?>> future;

    Task(Subscribable sub)
    {
      this.future = new FutureTask<>(() -> schedule(sub));
    }

    void activate()
    {
      future.run();
    }

    void cancel()
    {
      boolean interrupted = false;
      while (true) {
        try {
          future.get().cancel(false);
          break;
        }
        catch (ExecutionException ignore) {
          ignore.printStackTrace(); /* Cancellation is unnecessary. */
          break;
        }
        catch (InterruptedException ex) {
          interrupted = true; /* Keep waiting... */
        }
      }
      if (interrupted)
        Thread.currentThread().interrupt(); /* Reset interrupt state. */
    }

  }

}

@FunctionalInterface
interface Subscribable
{

  default long getPeriod()
  {
    return 4;
  }

  void invoke();

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33555545

复制
相关文章
matlab在axis,matlab中axis的用法
>> axis([0 2*pi -0.9 0.9]) 图 5.1.3 使用了图形修饰的 plot 函数绘制的正弦曲线 5.1.3 图形的比较显示 在一般默认的情况下,MATLAB 每次使用 plot ……
全栈程序员站长
2022/09/06
2.1K0
在MATLAB中RSA加密
[Modulus, PublicExponent, PrivateExponent] = GenerateKeyPair;
万木逢春
2019/05/10
1.9K0
PS处理简单的视频剪切
视频是什么?视频(Video)泛指将一系列静态影像以电信号的方式加以捕捉、纪录、处理、储存、传送与重现的各种技术。连续的图像变化每秒超过24帧(frame)画面以上时,根据视觉暂留原理,人眼无法辨别单幅的静态画面;看上去是平滑连续的视觉效果,这样连续的画面叫做视频。视频技术最早是为了电视系统而发展,但现在已经发展为各种不同的格式以利消费者将视频记录下来。网络技术的发达也促使视频的纪录片段以串流媒体的形式存在于因特网之上并可被电脑接收与播放。视频与电影属于不同的技术,后者是利用照相术将动态的影像捕捉为一系列的静态照片。
爱上歆随懿恫
2022/08/10
1.4K0
PS处理简单的视频剪切
eeglab在MATLAB中安装教程
1.在eeglab官网,如下图,在红框中有Download EEGLAB选项,点击该选项。
脑机接口社区
2020/06/29
2.1K0
unit在matlab中啥意思,unit8(matlab中uint8函数)
就是宏定义,代码中就用这些去定义变量 如uint16 a; 就表示定义了一个 无符号整形变量a (等价于 unsigned int a;)其他的同理 其作用是程序更加简洁 最大的作用是增.
全栈程序员站长
2022/09/30
1.5K0
FFMPEG音频视频开发: 命令行完成视频剪切与合成
一、环境介绍 操作系统介绍:win10 64位 FFMPEG版本: 4.4.2 QT版本: 5.12.6 二、操作命令 2.1 合成视频命令 ffmpeg.exe -f concat -i filelist.txt -c copy output.mp4 filelist.txt :存放合成视频的列表 列表格式例如: file '1_123.mp4' file '2_123.mp4' file '3_123.mp4' file '4_123.mp4' file '5_123.mp4' file '6_12
DS小龙哥
2022/01/12
5920
如何在 Vim 中复制,剪切,粘贴
Vim 以及它的前辈 Vi 在 macOS 和基本上所有的 Linux 版本上都预装了。在你喜欢的编辑器还没有安装的情况下,对 Vim 有一些基本了解是很有用处的。
雪梦科技
2020/05/11
41.5K0
如何在 Vim 中复制,剪切,粘贴
matlab 汽车振动,matlab在汽车振动分析
Matlab在振动分析中的应用刘迪辉2011-10-20大家学了游泳理论,现在我们借助MATLAB软件,来练习一下游泳!实际问题:客车的振动分析• 客车样车路试过程中却出现了令人意想不到的一系列振动问题 ,主要表现为 : (1) 汽车起动时发动机抖动厉害 ; (2) 当车速在 40 km/ h 左右时 ,整车有共振现象 ; (3) 当车速在 85 km/ h 左右时 ,整车有明显振动 ; (4) 当车速超过 118 km/ h 时 ,驾驶区及方向盘有强烈振感。• 由于上述振动的存在 ,一方面大大降低了该车驾乘的舒适性和运行中的安全性 ;另一方面 ,造成一些主要总成件 (如发动机、变速器、后桥等 ) 的早期损坏 ;同时 ,也使得汽车上很多结构件出现疲劳断裂 ,从而进一步加剧了整车或局部振动。• 选自王卫鸿 《 YBL6850C24aH》 型客车振动问题及解决方案,客车技术与研究, 2005.5Simulink Demo• This demo describes a simplified half-car model that includes an independent front and rear vertical suspension. 振动问题• 多自由度• 二自由度• 单自由度• 实际问题• ( 1)理论方法• ( 2) Matlab(实现理论算法)• (3) 有限元方法 Ansys, Abaqus, Natran等• ( 4) 试验方法难易• 建立力学模型、微分方程• 求解微分方程,得到响应特性振动方程时间 t响应函数 x(t)质量 m刚度 k阻尼 c时间 t激励函数 f(t)( 1) 已知激励函数和响应函数,求系统固有特性( 2) 已知固有特性,求在一定激励条件下的响应函数汽车悬架单自由度分析• 例 2.15 质量 m=2450kg的汽车,悬架总的刚度为 160000N/m, 减振器阻尼系数为 7135.6Ns/m,求该车辆受到 100 kg的简谐加载时的,车身的上下运动方程 .• 简谐激励首先得设定参数 F0, w, 和时间向量 t, 求每个时间的 f(t)理论公式该函数由普通微分方程求解方法其中提问:为什么要如此参数化?方便求解和定义联系起来固有频率 系统阻尼
全栈程序员站长
2022/11/03
7180
matlab 汽车振动,matlab在汽车振动分析
matlab是fmincon,matlab中fmincon
标签: fmincon| MATLAB非线性优化fmincon_数学_自然科学_专业资料。MATLAB非线性优化函数fmincon的详细整理 active-set and sqp algorithms 不接受用户提供的海塞矩阵……
全栈程序员站长
2022/08/12
2K0
python剪切文件
#剪切文件import os def shear_dile(src,dst): if os.path.isdir(src): if not os.listdir(src): os.rmdir(src) print('移除空目录: ' + src) else : for d in os.listdir(src): shear_dile(os.path.join(src
狼啸风云
2020/08/10
8510
在MATLAB中使用opencv
我们来说说第二类,需要做的事情是先编译opencv的源码、再编译matlab可用的mex文件夹,这两步的编译器必须是同一个,而最近几年的新版本matlab都推荐使用MinGW-w64编译器来使用mex、可是mexopencv提供的编译辅助函数在Windows系统上默认使用Visual Studio或者Windows SDK来编译,如果觉得自己需要Visual Studio的其他功能,安装一下也是挺好的
万木逢春
2019/10/09
6.3K0
在MATLAB中使用opencv
在python中运行MATLAB代码从而实现批量运算结果
在安装好python和matlab的电脑上,如果需要做一些流程化的内容,matlab这个方面不擅长,此时可以借助python来开发,
用户9925864
2023/09/05
6760
在python中运行MATLAB代码从而实现批量运算结果
FFmpeg优化 苏宁PP体育视频剪切效率提升技巧
苏宁旗下PP体育所在的直播行业,每天有无数视频原始数据需要进行分类存储、渲染处理。处理这些视频,一个很重要的方面,就是要将长时段的直播视频切割成不定时长,不定画面组的短视频,以匹配现代用户碎片化的消费时间。尤其是体育赛事直播行业,在直播前的垫场片花、直播中的即时快看、直播后的全场集锦和精华镜头,都需要对大量的视频作剪切/压制处理。而且因为体育赛事直播行业的特殊性,对于直播中和直播后的精彩镜头,集锦类视频片段,要求必须能及时处理视频,并发布到用户端。这对视频的处理效率提出了非常高的要求。
LiveVideoStack
2021/09/01
7920
信号与系统实验一 信号在MATLAB中的表示
 3.用下列函数各画一图,参数自定。 sinc,rectpuls,square,tripuls,sawtooth
timerring
2022/07/20
1.4K0
信号与系统实验一 信号在MATLAB中的表示
matlab中错误使用fmincon,MATLAB中fmincon 函数问题
[w,fval]=fmincon(@fun2,w0,[],[],Aeq,Beq,@myfuntestcon,options)
全栈程序员站长
2022/09/01
1K0
matlab中错误使用fmincon,MATLAB中fmincon 函数问题
Canvas 剪切图片
/** * 剪切图像 */ function initDemo8(){ var canvas = document.getElementById("demo8"); if (!canvas) return; var context = canvas.getContext("2d"); var img = new Image(); img.src = "images/timg3.jpg"; img.onload = function () {
就只是小茗
2018/03/07
2.1K0
matlab中的im2bw函数_matlab中tofloat
这种du格式将一张二值图像显示在屏zhi幕上, 允许用户使用鼠标在图像上点几个点, 这几个点围成的区域即要填充的区域。要以这种交互方式操作, BW必须是一个二维的图像。用户可以通过按Backspace键或者Delete键来取消之前选择的区域;通过shift+鼠标左键单击或者鼠标右键单击或双击可以确定选择区域。
全栈程序员站长
2022/09/30
1.2K0
matlab fopen fread_matlab中prctile函数
大家好,又见面了,我是你们的朋友全栈君。 matlab中length函数 length(x)在matlab中是什么意思?小编能记住你的一点一滴,你却忘了小编的一丝一毫。 if length(h)>1
全栈程序员站长
2022/09/30
1.4K0
matlab fopen fread_matlab中prctile函数
Matlab循环语句_matlab中if语句的用法
《matlab循环语句》由会员分享,可在线阅读,更多相关《matlab循环语句(9页珍藏版)》请在人人文库网上搜索。
全栈程序员站长
2022/11/10
3.1K0
点击加载更多

相似问题

在iPhone上剪切视频

14

在Reactjs上传前剪切视频

19

Matlab获取剪切量

11

在Ubuntu中用ffmpeg剪切视频

14

在MatLab中播放视频

23
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档