`

频繁调用互斥操作——Java

阅读更多

       开发中遇到的问题:看到项目先前实现的代码,有一个逻辑处理,要完成两个界面的切换,而且这个两个界面的切换会共同设置系统的同一个资源的状态,且设置状态的操作(系统中间件已经做了互斥)比较耗时。先前的代码采用了新建线程来设置资源状态来保证主线程不被阻塞。这就出现了一个问题,如果频繁操作切换的话,就会出现系统资源的状态错乱。

       应用调用:

Thread call state(true);

Thread call state(false);

Thread call state(true);

Thread call state(false);

Thread call state(true);

...

Thread call state(true);

    实际执行结果:

Thread run state(true);

Thread run state(false);

Thread run state(true);

Thread run state(true);

Thread run state(false);

...

Thread run state(false); or Thread run state(true);

        执行结果可以看出,在频繁调用的时候就出现与调用顺序不对应的问题,调用结束的结果可能会是错误的。

    

        究其原因是因为只考虑了耗时操作采用线程来处理,没有对线程进行管理,造成一个操作结束后,其他等待的线程抢占运行,结果肯定会出现不对应调用的情况。

 

       解决方法:

       对于状态这种设置的处理,优先要保证状态的正确性,如果在执行true的时候,又调用设置false,再调用设置true。最终结果会是true。那么在执行第一次true的时候,来了两个操作,可以选择丢弃中间设置false的操作,来提高响应效率和保证结果正确。

       另外线程的组织管理,没有比线程池好的。

    频繁调用帮助类:  

/**
 * 如果你遇到这种场景:应用需要频繁的调用两个互斥的耗时操作,而且要保证效率与结果正确的话,这个帮助类对于你可能会有用。
 * Created by leonhover on 13-12-11.
 */
public class FrequencyTaskHelper {

    /**
     * 线程池
     */
    private ThreadPoolExecutor threadPool = null;

    /**
     * 任务队列,大小为1
     */
    private ArrayBlockingQueue queue = new ArrayBlockingQueue<Runnable>(1);

    public FrequencyTaskHelper() {
        //创建线程池,只有一个线程在运行,采用DiscardOldestPolicy机制(采用其他也可以,因为用不到,我们手动清空任务队列)
        threadPool = new ThreadPoolExecutor(1, 1, 50, TimeUnit.SECONDS,
                queue,
                new ThreadPoolExecutor.DiscardOldestPolicy());
    }

    /**
     * 在线程池中执行操作,不一定被执行
     *
     * @param runnable 操作任务
     */
    public void execute(Runnable runnable) {
        //清空任务队列
        queue.clear();
        //在线程池中执行,如果没有任务运行则执行,要不就排队,排队后又可能被丢弃。
        threadPool.execute(runnable);
    }
}

    测试类

 /**
     * 测试任务,任务延迟有20毫秒
     */
    public static class TestOption implements Runnable {

        private String name = null;

        public TestOption(String str) {
            name = str;
        }

        @Override
        public void run() {
            System.out.println("Task " + name + " start ");
            System.out.println("Task " + name + " executed!");
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Task " + name + " end ");
        }
    }

    //程序入口
    public static final void main(String[] args) {
        System.out.println("Start");
        FrequencyTaskHelper helper = new FrequencyTaskHelper();
        for (int i = 0; i < 100000; i++) {
            TestOption opt = new TestOption("opt" + i);
            helper.execute(opt);
        }
    }

 

分享到:
评论

相关推荐

    线程——基本线程的应用和线程调用控件

    - 线程同步与互斥:为了防止线程间的竞态条件,可以使用锁(如Java的`synchronized`关键字,C#'s `Monitor`类)或其他同步机制。 4. **线程调度**: - 线程调度器负责决定哪个线程应该获得CPU执行权。调度策略...

    面试题解惑系列(十)——话说多线程

    这是因为`start()`方法会调用`run()`方法,并且在Java中,只有通过`start()`方法调用的`run()`才会在新的线程上下文中执行,从而实现多线程。 **四、线程同步与互斥** 在多线程环境下,为了防止数据不一致性,Java...

    Java多线程下载网络图片

    在Java编程中,多线程是一项关键技能,尤其在处理并发任务时,如我们的示例——"Java多线程下载网络图片"。这个场景展示了如何利用多线程技术提高程序性能,减少用户等待时间,同时优化系统资源的使用。下面我们将...

    Java秋招复习资料 interview-notebook.pdf

    ### Java秋招复习资料——操作系统基础 #### 一、操作系统基本特征 1. **并发**:并发是指在宏观上能够同时运行多个程序的能力。而并行则是指在同一时刻能够执行多个指令,通常需要硬件的支持,比如多核心处理器或...

    Java小项目

    3. **同步与互斥**:学习`synchronized`关键字,它是Java中实现线程安全的主要手段,用于防止数据竞争和确保共享资源的访问有序性。 4. **wait(), notify(), notifyAll()**:这些方法在`Object`类中定义,用于线程...

    java面试题大全-葵花宝典和面试编程

    Java面试题大全——葵花宝典与面试编程 在Java开发者的职业生涯中,面试是必不可少的一环,尤其对于初入职场或寻求职业发展的毕业生来说,准备充分的面试题集至关重要。"java面试题大全-葵花宝典和面试编程"正是...

    火车站售票系统

    火车站售票系统是一个典型的多用户并发访问的分布式应用,它的核心在于如何有效地管理和分配有限的资源——火车票。在这个系统中,多线程技术是关键,它使得系统能够同时处理多个购票请求,提升服务效率和用户体验。...

Global site tag (gtag.js) - Google Analytics