当前位置: 首页 > 知识库问答 >
问题:

为什么信号灯不停止穿插?

司徒泰
2023-03-14

我使用信号量,我希望当列表大小为零时,线程等待其他线程,但为什么信号量不停止执行?信号量不是像notify和wait一样工作吗?

结果:add remove add Exception in thread“Thread-2”java.lang.IndexOutOfBoundsException:Index:0,Size:0

 ArrayList<String> list = new ArrayList<>();
            Semaphore semaphore = new Semaphore(0);
    
            new Producer(list, semaphore).start();
            new Producer(list, semaphore).start();
            new Customeer(list, semaphore).start();
            new Customeer(list, semaphore).start();
    //////////
        static class Customeer extends Thread {
    
            private List<String> list;
            private Semaphore semaphore;
    
            public Customeer(List<String> list, Semaphore semaphore) {
                this.list = list;
                this.semaphore = semaphore;
            }
    
            @Override
            public void run() {
    
    
                synchronized (list) {
                    if (list.size() == 0) {
                        try {
                            semaphore.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                        list.remove(0);
                        System.out.println("remove");
                }
            }
        }
    
        static class Producer extends Thread {
    
            private Semaphore semaphore;
            private List<String> list;
    
            public Producer(List<String> list, Semaphore semaphore) {
                this.list = list;
                this.semaphore = semaphore;
            }
    
            @Override
            public void run() {
    
                synchronized (list) {
    
                    list.add("hello");
                    semaphore.release();
                    System.out.println("add");
    
                }
    
            }
        }
    
    }

共有1个答案

禄星腾
2023-03-14

您似乎混淆了信号量和同步。当您希望允许n个线程一次访问相同的资源时,就会使用信号量。如果只允许1个线程访问资源,则使用同步时,[n可以是1]。

使用信号量的解决方案

// Java implementation of a producer and consumer 
// that use semaphores to control synchronization. 

import java.util.concurrent.Semaphore; 

class Q { 
    // an item 
    int item; 

    // semCon initialized with 0 permits 
    // to ensure put() executes first 
    static Semaphore semCon = new Semaphore(0); 

    static Semaphore semProd = new Semaphore(1); 

    // to get an item from buffer 
    void get() 
    { 
        try { 
            // Before consumer can consume an item, 
            // it must acquire a permit from semCon 
            semCon.acquire(); 
        } 
        catch (InterruptedException e) { 
            System.out.println("InterruptedException caught"); 
        } 

        // consumer consuming an item 
        System.out.println("Consumer consumed item : " + item); 

        // After consumer consumes the item, 
        // it releases semProd to notify producer 
        semProd.release(); 
    } 

    // to put an item in buffer 
    void put(int item) 
    { 
        try { 
            // Before producer can produce an item, 
            // it must acquire a permit from semProd 
            semProd.acquire(); 
        } 
        catch (InterruptedException e) { 
            System.out.println("InterruptedException caught"); 
        } 

        // producer producing an item 
        this.item = item; 

        System.out.println("Producer produced item : " + item); 

        // After producer produces the item, 
        // it releases semCon to notify consumer 
        semCon.release(); 
    } 
} 

// Producer class 
class Producer implements Runnable { 
    Q q; 
    Producer(Q q) 
    { 
        this.q = q; 
        new Thread(this, "Producer").start(); 
    } 

    public void run() 
    { 
        for (int i = 0; i < 5; i++) 
            // producer put items 
            q.put(i); 
    } 
} 

// Consumer class 
class Consumer implements Runnable { 
    Q q; 
    Consumer(Q q) 
    { 
        this.q = q; 
        new Thread(this, "Consumer").start(); 
    } 

    public void run() 
    { 
        for (int i = 0; i < 5; i++) 
            // consumer get items 
            q.get(); 
    } 
} 

// Driver class 
class PC { 
    public static void main(String args[]) 
    { 
        // creating buffer queue 
        Q q = new Q(); 

        // starting consumer thread 
        new Consumer(q); 

        // starting producer thread 
        new Producer(q); 
    } 
} 

使用同步的解决方案

// Java program to implement solution of producer 
// consumer problem. 

import java.util.LinkedList; 

public class Threadexample { 
    public static void main(String[] args) 
        throws InterruptedException 
    { 
        // Object of a class that has both produce() 
        // and consume() methods 
        final PC pc = new PC(); 

        // Create producer thread 
        Thread t1 = new Thread(new Runnable() { 
            @Override
            public void run() 
            { 
                try { 
                    pc.produce(); 
                } 
                catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
            } 
        }); 

        // Create consumer thread 
        Thread t2 = new Thread(new Runnable() { 
            @Override
            public void run() 
            { 
                try { 
                    pc.consume(); 
                } 
                catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
            } 
        }); 

        // Start both threads 
        t1.start(); 
        t2.start(); 

        // t1 finishes before t2 
        t1.join(); 
        t2.join(); 
    } 

    // This class has a list, producer (adds items to list 
    // and consumber (removes items). 
    public static class PC { 

        // Create a list shared by producer and consumer 
        // Size of list is 2. 
        LinkedList<Integer> list = new LinkedList<>(); 
        int capacity = 2; 

        // Function called by producer thread 
        public void produce() throws InterruptedException 
        { 
            int value = 0; 
            while (true) { 
                synchronized (this) 
                { 
                    // producer thread waits while list 
                    // is full 
                    while (list.size() == capacity) 
                        wait(); 

                    System.out.println("Producer produced-"
                                    + value); 

                    // to insert the jobs in the list 
                    list.add(value++); 

                    // notifies the consumer thread that 
                    // now it can start consuming 
                    notify(); 

                    // makes the working of program easier 
                    // to understand 
                    Thread.sleep(1000); 
                } 
            } 
        } 

        // Function called by consumer thread 
        public void consume() throws InterruptedException 
        { 
            while (true) { 
                synchronized (this) 
                { 
                    // consumer thread waits while list 
                    // is empty 
                    while (list.size() == 0) 
                        wait(); 

                    // to retrive the ifrst job in the list 
                    int val = list.removeFirst(); 

                    System.out.println("Consumer consumed-"
                                    + val); 

                    // Wake up producer thread 
                    notify(); 

                    // and sleep 
                    Thread.sleep(1000); 
                } 
            } 
        } 
    } 
} 

阅读参考资料以获得更清晰的信息

信号量:https://www.geeksforgeeks.org/producer-consumer-solution-using-semaphores-s/

同步:https://www.geeksforgeeks.org/producer-consumer-solution-using-threads-Java/

 类似资料:
  • 我有一个ArrayList,它应该在包含0个以上对象时启动报警服务,在包含0个对象时停止报警服务。 这是报警服务类。 这是on Receive方法广播接收器类 问题是,即使调用了报警服务的onDestroy方法,通知也不会停止。 我错过什么了吗? 谢谢

  • 第一个线程组-Wisebuy 1-1在2019-04-30 15:46:11,559开始 我将上升周期设置为1秒,为什么线程组-Wisebuy 1-5891在2019-04-30 15:46:15,541开始? 我将持续时间设置为2秒,为什么线程组-Wisebuy 1-7239在2019-04-30 15:46:18,767停止?

  • 我想在try块中捕获PyCharm的stop信号(当stop被按下时),但是我不知道这个信号是什么或者如何在代码中捕获它。JetBrains在他们的文档中没有提供这方面的见解。 我尝试将其捕获为,但它似乎根本不是异常。 这在编程上是完全可以捕获的吗?

  • 我的代码使用readTextFile读取日志文件,当我在Flink(< code >/opt/Flink-1 . 0 . 3/bin/Flink run-m yarn-cluster-yn 2/home/Flink/Flink-JSON-0.1 . jar )中运行jar时,它成功处理了里面的行,并停止了我的应用程序,而不是等待新的行。我做这件事需要一些参数吗? 先谢谢你了

  • 问题内容: 在我的应用程序中,我想在新用户注册时在某些表中创建条目。例如,我要创建一个用户个人资料,然后将参考他们的公司和一些其他记录。我用post_save信号实现了这一点: 运行时效果很好。我可以使用admin创建一个新用户,其他三个表也可以获取有意义的条目。(除非是雇员,因为保存时未在管理员表单中填写user.first_name和user.last_name。我仍然不明白为什么要这样做)

  • 问题内容: 基本上,一切似乎都可以正常运行并启动,但是由于某些原因,我无法调用任何命令。我已经很轻松地环顾了一个小时,然后看了一些示例/观看视频,但我终生无法找出问题所在。代码如下: 我在中拥有的调试输出实际上可以正常工作并做出响应,并且整个bot都可以运行,没有任何异常,但是它只是不会调用命令。 问题答案: 覆盖提供的默认值将禁止运行任何其他命令。要解决此问题,请在的末尾添加一行。例如: 默认值