[CareerCup] 16.5 Semphore 信号旗

简介:

16.5 Suppose we have the following code:
public class Foo {
public Foo() { . . . }
public void first() { ... }
public void second() { ... }
public void thirdQ { ... }
}
The same instance of Foo will be passed to three different threads. ThreadA will call first, threads will call second, and threadC will call third. Design a mechanism to ensure that first is called before second and second is called before third.

按照题目中要求的顺序即需满足在执行second()前检测first()是否完成了,在执行third()前检测second()是否完成了,由于我们需要考虑线程安全,所以布尔型的标记不行,那么使用锁呢,看如下代码:

import java.util.concurrent.locks.ReentrantLock;
public class FooBad {
    public int pauseTime = 10000;
    public ReentrantLock lock1;
    public ReentrantLock lock2;
    
    public FooBad() {
        try {
            lock1 = new ReentrantLock();
            lock2 = new ReentrantLock();
            lock1.lock();
            lock2.lock();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }   
public void first() {
        try {
            System.out.println("Started Executing 1");
            Thread.sleep(pauseTime);
            System.out.println("Finished Executing 1");
            lock1.unlock();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
public void second () {
        try {
            lock1.lock();
            lock1.unlock();
            System.out.println("Started Executing 2");
            Thread.sleep(pauseTime);
            System.out.println("Finished Executing 2");
            lock2.unlock();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
public void third() {
        try {
            lock2.lock();
            lock2.unlock();
            System.out.println("Started Executing 3");
            Thread.sleep(pauseTime);
            System.out.println("Finished Executing 3");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
public class MyThread extends Thread {
private String method;
private FooBad foo;
public MyThread(FooBad foo, String method) {
        this.method = method;
        this.foo = foo;
    }
public void run() {
        if (method == "first") {
            foo.first();
        } else if (method == "second") {
            foo.second();
        } else if (method == "third") {
            foo.third();
        }
    }
}
public class j {
    public static void main(String[] args) {
        FooBad foo = new FooBad();
        
        MyThread thread1 = new MyThread(foo, "first");
        MyThread thread2 = new MyThread(foo, "second");
        MyThread thread3 = new MyThread(foo, "third");
        
        thread3.start();
        thread2.start();
        thread1.start();
    }
}

上述代码并不能很好的完成题目中要求的顺序,因为锁的所有权的问题。一个线程操作一个锁,当别的线程是无法解这个线程的锁的,所以用锁是不行的。我们可以使用信号旗Semaphores,参见代码如下:

import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Foo {
public int pauseTime = 1000;
public Semaphore sem1;
public Semaphore sem2;
public Foo() {
        try {
            sem1 = new Semaphore(1);
            sem2 = new Semaphore(1);
            sem1.acquire();
            sem2.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
public void first() {
        try {
            System.out.println("Started Executing 1");
            Thread.sleep(pauseTime);
            System.out.println("Finished Executing");
            sem1.release();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
public void second() {
        try {
            sem1.acquire();
            sem1.release();
            System.out.println("Started Executing 2");
            Thread.sleep(pauseTime);
            System.out.println("Finished Executing 2");
            sem2.release();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
public void third() {
        try {
            sem2.acquire();
            sem2.release();
            System.out.println("Started Executing 3");
            Thread.sleep(pauseTime);
            System.out.println("Finished Executing 3");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
public class MyThread extends Thread {
private String method;
private Foo foo;
public MyThread(Foo foo, String method) {
        this.method = method;
        this.foo = foo;
    }
public void run() {
        if (method == "first") {
            foo.first();
        } else if (method == "second") {
            foo.second();
        } else if (method == "third") {
            foo.third();
        }
    }
}
public class j {
public static void main(String[] args) {
        Foo foo = new Foo();
        
        MyThread thread1 = new MyThread(foo, "first");
        MyThread thread2 = new MyThread(foo, "second");
        MyThread thread3 = new MyThread(foo, "third");
        thread3.start();
        thread2.start();
        thread1.start();
    }
}

本文转自博客园Grandyang的博客,原文链接:信号旗[CareerCup] 16.5 Semphore ,如需转载请自行联系原博主。

相关文章
|
Linux
在Linux中使用rsync进行备份时如何排除文件和目录?
在Linux中使用rsync进行备份时如何排除文件和目录?
697 1
在Linux中使用rsync进行备份时如何排除文件和目录?
|
消息中间件 数据可视化 Oracle
RocketMQ安装部署 (Linux)
RocketMQ安装部署 (Linux)
1677 1
|
10月前
|
存储 NoSQL 安全
Redis的两种持久化方式---RDB、AOF
通过本文的介绍,我们详细讲解了Redis的两种主要持久化方式:RDB和AOF。每种方式都有其独特的优缺点和适用场景。在实际应用中,可以根据具体需求选择合适的持久化方式,或者同时启用RDB和AOF,以达到最佳效果。希望本文能帮助您更好地理解和应用Redis的持久化机制,构建高效、可靠的数据存储解决方案。
1035 79
|
安全 测试技术 Android开发
移动应用开发
移动应用开发
336 9
|
监控 测试技术
如何进行系统压力测试?
【10月更文挑战第11天】如何进行系统压力测试?
860 34
|
SQL Oracle 关系型数据库
Oracle数据库优化方法
【10月更文挑战第25天】Oracle数据库优化方法
263 7
|
安全 Linux Shell
常见的 Linux 命令大全(表格形式)
常见的 Linux 命令大全(表格形式)
866 1
|
数据可视化 API 索引
DOTween教程☀️DOTween的使用教程
DOTween教程☀️DOTween的使用教程
|
网络协议 网络虚拟化 网络架构
网络之路25:VLAN进阶实验-Super VLAN
网络之路25:VLAN进阶实验-Super VLAN
|
数据库
设计分E-R图的步骤
设计分E-R图的步骤
433 0