`
luccs624061082
  • 浏览: 84981 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论
阅读更多
  线程经常需要协调它们的活动,最常用的协调方法是保护块。这样的块是以轮询一个条件开始,这个条件值必须是true,在块处理前。为了正确做到这样,有大量的步骤需要遵守。

  例如,guardedJoy 是一个方法,直到一个共享变量joy被另外一个线程设置了才会执行。这样的方法,理论上,简单的循环直到条件满足,但是了这样的循环是耗费的,因为它不断地在等待中执行。

  public void guardedJoy() {
    // Simple loop guard. Wastes
    // processor time. Don't do this!
    while(!joy) {}
    System.out.println("Joy has been achieved!");
  }

   一种更有效的保护是调用object.wait来暂停当前线程。wait的调用不会返回直到领一个线程已经发不了一个通知,一些特殊的事件可能发生。虽然不是这个线程正在等待的事件:
  
   public synchronized void guardedJoy() {
    // This guard only loops once for each special event, which may not
    // be the event we're waiting for.
    while(!joy) {
        try {
            wait();
        } catch (InterruptedException e) {}
    }
  

   注意:总是调用循环中的wait来测试正在等待的条件。不要假设中断(interrupt)是你正在等待的条件或者那个条件是true。

   像许多暂停执行的方法,wait会抛出InterruptedException。在这个例子中,我们能忽略这个异常,仅仅关注joy的值。

   为什么这个版本的guardedJoy是同步的?假设d是我们用来调用wait的对象。当一个线程调用d.wait,它必须拥有d的内在锁---否则将抛出一个错误。在一个同步方法中调用wait是一种简单的方式获取内在锁。

   当wait被调用,那个线程就释放锁并暂停执行。在不远的将来,另外一个线程将获取同样的锁并调用object.notifyAll,通知在这个锁上等待的所有线程,一些重要的事情发生了。
   public synchronized notifyJoy() {
    joy = true;
    notifyAll();
   }

    在第二个线程释放了锁后的一段时间,第一个线程重新获取锁并从wait的调用通过返回继续执行。

    注意:有第二个通知方法,notify,唤醒一个单一线程。因为notify不允许你指定要唤醒的线程,只有在大规模并行的应用程序中有用---即,程序中有大量的线程,所有的做那相似的工作。在这样的应用程序中,你不必在意哪个线程被唤醒。

    让我们使用保护块创建一个生产者--消费者应用程序。这类的应用在两个线程之间共享数据:生产者创建数据,消费者使用数据做一些事情。两个线程使用一个共享对象通信。协调就是必须的:在生产者传递数据前,消费者不必试着去获取它,并且生产者也不必试着去传递新的数据,如果消费者还没有获取旧的数据。

    在这个例子中,数据是一系列的文本信息,通过一个Drop的对象实现共享。

    public class Drop {
    // Message sent from producer
    // to consumer.
    private String message;
    // True if consumer should wait
    // for producer to send message,
    // false if producer should wait for
    // consumer to retrieve message.
    private boolean empty = true;

    public synchronized String take() {
        // Wait until message is
        // available.
        while (empty) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        // Toggle status.
        empty = true;
        // Notify producer that
        // status has changed.
        notifyAll();
        return message;
    }

    public synchronized void put(String message) {
        // Wait until message has
        // been retrieved.
        while (!empty) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        // Toggle status.
        empty = false;
        // Store message.
        this.message = message;
        // Notify consumer that status
        // has changed.
        notifyAll();
    }
  }


  生产者线程,用Producer定义,发送一系列相似的信息。字符串”DONE“表明所有的消息已经发送了。为了模仿现实世界中不可预知的性质,生产者在消息之间以随机间隔暂停。

  import java.util.Random;

public class Producer implements Runnable {
    private Drop drop;

    public Producer(Drop drop) {
        this.drop = drop;
    }

    public void run() {
        String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };
        Random random = new Random();

        for (int i = 0;
             i < importantInfo.length;
             i++) {
            drop.put(importantInfo[i]);
            try {
                Thread.sleep(random.nextInt(5000));
            } catch (InterruptedException e) {}
        }
        drop.put("DONE");
    }
}

消费者线程,以Consumer定义,简单地接受消息并打印出来,直到获取了”DONE“字符串。线程也以随机间隔暂停

  import java.util.Random;

public class Consumer implements Runnable {
    private Drop drop;

    public Consumer(Drop drop) {
        this.drop = drop;
    }

    public void run() {
        Random random = new Random();
        for (String message = drop.take();
             ! message.equals("DONE");
             message = drop.take()) {
            System.out.format("MESSAGE RECEIVED: %s%n", message);
            try {
                Thread.sleep(random.nextInt(5000));
            } catch (InterruptedException e) {}
        }
    }
}
 
  最后,这是主线程,以ProducerConsumerExample 定义。启动了生产者和消费者线程。
 
  public class ProducerConsumerExample {
    public static void main(String[] args) {
        Drop drop = new Drop();
        (new Thread(new Producer(drop))).start();
        (new Thread(new Consumer(drop))).start();
    }
}

  注意: The Drop class was written in order to demonstrate guarded     blocks. To avoid re-inventing the wheel, examine the  existing data structures in the Java Collections Framework before    trying to code your own data-sharing objects. For more information,  refer to the Questions and Exercises section.



分享到:
评论

相关推荐

    scalac-guardedblocks-plugin:简单的Scala编译器插件

    `scalac-guardedblocks-plugin`是一个针对Scala编译器的轻量级插件,它的主要目标是提供一种机制,允许开发者定义"受保护的块"。这种块类似于Java中的try-catch结构,但更简洁且具有更广泛的用途。通过这个插件,...

    laravel中的fillable和guarded属性详解

    选择使用哪一个取决于你的具体需求,白名单 `fillable` 更倾向于开放指定的属性,而黑名单 `guarded` 更侧重于保护敏感字段不被意外更新。正确地使用这两个属性能帮助你构建更安全、更可控的 Laravel 应用。

    guarded-array:边界检查数组

    保护阵列 用于帮助调试的慢速边界检查数组。 例子 var guard = require ( 'guarded-array' ) //First create any old array var array = [ 0 , 1 , 2 , 3 , 4 , 5 ] //Then we protect it using guard! var ...

    java oracle并发官方教程

    Guarded Blocks是一种同步构造,它用于等待某个条件变为真。它通过检查条件和等待条件满足的循环来实现,通常利用wait/notify机制来控制线程的执行。 ### 不可变对象(Immutable Objects) 在并发编程中,不可变...

    逻辑编程语言:GHC (Guarded Horn Clauses).zip

    史上最全编程语言全套教程,共99门编程语言,包括: 函数式编程语言 壳编程语言 常见编程语言 并行编程语言 数据分析编程语言 数据库查询语言 系统编程语言 脚本编程语言 逻辑编程语言 面向对象编程语言 ...

    guarded-string:防止在应用程序中意外地在字符串中引入XSSKong

    yarn add guarded-string 用法 重要的! 应该将其用于防止XSS攻击之类的东西,而不是用于隐藏敏感信息。 import guardedString from 'guarded-string' ; const myString = guardedString `My very important (but ...

    guarded-bayou-7383

    JAX-RS 模板应用程序这是使用 JAX-RS 的轻量级 RESTful API 的模板。 示例代码是获取当前时间的调用。在本地运行应用程序首先构建: $mvn clean install然后运行它: $ java -cp target/classes:target/dependency/*...

    纳米ASIC 的ESD保护电路基础-综合文档

    I/O端口通常设置有T形网络、GDT( Guarded Diode Transistor)或TVS(Transient Voltage Suppressor)等结构,以迅速分流ESD电流,避免进入核心电路。同时,内部电路的保护通常包括多晶硅栅极氧化层增强、源/漏掺杂...

    周玉川-2017221302006-第三次作业1

    3. GS (Guarded Stack) 保护机制: GS 提供了一种栈保护机制,通过动态生成的canary值来检测栈溢出。在函数调用前后,canary值会被计算和验证,异常则会导致程序终止。为了增强安全性,还会额外加入cookie和栈中...

    GuardedCommands:用于模拟防护命令语言的Python程序

    防护命令语言六月7,2018 CS522正式语言和自动机20183111金李涵概括 2018年Spring正式语言和自动机理论项目1〜2 防护命令语言(以下称为GCL)解析和执行功能的实现语句语法说明中止论文说“做任何事情”,但实际上并...

    finally分析

    // Guarded body } __finally { // Termination handler } ``` 在这个语法结构中,不论`__try`块中的代码如何退出,`__finally`块中的代码都将被执行,除非使用了`ExitProcess`, `ExitThread`, `TerminateProcess...

    essential-java

    - **Guarded Blocks**:一种等待条件满足后再继续执行的线程同步机制。 - **不可变对象**:一旦创建后,其状态就不能被改变的对象,有助于简化并发编程。 - **高级并发对象**:如CountDownLatch、Semaphore等,...

    Laravel开发-attribute-purging

    在Laravel框架中,开发过程中有时需要控制模型的属性,以确保某些数据不会被保存到数据库中。这就是“attribute purging”(属性清除)的概念,它...在实践中,一定要考虑数据保护和隐私政策,确保符合相关法规和标准。

    aqs-并发编程笔记.pdf

    并发编程笔记中的知识点涵盖了保护性暂停模式(Guarded Suspension Design Pattern)的定义、实现与分析,以及在Java中如何通过GuardedObject对象来实现多线程间的结果传递和超时处理。以下是详细的知识点梳理: 1....

    Laravel开发-fillable

    如果你没有明确声明哪些字段是`fillable`的,那么默认所有字段都是`guarded`的。例如: ```php protected $guarded = ['password']; ``` 在这个例子中,除了`password`字段,其他所有字段都可以批量赋值。 四、...

    周玉川-2017221302006-第三次作业2

    3. **GS (Guarded Stack)** 保护机制:GS 是一种栈保护技术,通过在栈中插入一个随机生成的“cookie”来检测栈溢出。它在函数执行前后进行校验,确保栈的完整性。为了增强安全性,还会对栈变量进行重新排序,防止...

    CFAR算法matlab程序

    2. **CFAR GO(Guarded Outer Window,带有保护带的外部窗口)**:此算法在AC的基础上增加了保护带,避免了目标自身对噪声估计的影响。`cfar_go_test.m`和`cfar_go.m`文件展示了如何设置和使用保护带。 3. **CFAR ...

    Laravel开发-laravel-xss-filter

    在Laravel框架中,开发过程中保护应用程序免受跨站脚本(XSS)攻击是非常重要的。XSS是一种常见的Web安全漏洞,它允许攻击者通过注入恶意脚本到网页上,来窃取用户的数据或者控制用户的浏览器行为。"laravel-xss-...

    windows 缓冲区溢出

    4. **GS(Guarded Stack)**:在栈帧中添加一个安全cookie,用于检测栈溢出。如果cookie被修改,程序将终止。 三、缓冲区溢出的突破技巧 尽管有这些保护机制,攻击者仍然可以寻找漏洞绕过防护。常见的方法包括: ...

Global site tag (gtag.js) - Google Analytics