【问题标题】:Understanding Semaphores...了解信号量...
【发布时间】:2013-12-24 21:47:55
【问题描述】:

我在这里有一个代码,用于解释信号量是如何工作的。无论我多么努力,我都不理解下面的行以及如何调用信号量的代码。

基本上,代码试图模拟许多正在建立的连接......

import java.util.concurrent.Semaphore;

public class Connection {

    private static Connection instance = new Connection();

    private Semaphore sem = new Semaphore(10, true);

    private int connections = 0;

    private Connection() {

    }

    public static Connection getInstance() {
        return instance;
    }

    public void connect() {
        try {
            sem.acquire();
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        try {
            doConnect();
        } finally {

            sem.release();
        }
    }

    public void doConnect() {

        synchronized (this) {
            connections++;
            System.out.println("Current connections: " + connections);
        }

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        synchronized (this) {
            connections--;
        }

    }
}

主类文件..

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


public class App {

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newCachedThreadPool();

        for(int i=0; i < 200; i++) {
            executor.submit(new Runnable() {
                public void run() {
                    Connection.getInstance().connect();
                }
            });
        }

        executor.shutdown();

        executor.awaitTermination(1, TimeUnit.DAYS);
    }

}

我不理解运行部分

public void run() {
    Connection.getInstance().connect();
}

我们如何从上面调用连接方法?在我看来,连接输出应该始终为一个,因为正在调用新线程。令人惊讶的是,但这从未发生过。

【问题讨论】:

  • 您可能希望声明connections volatile 以使其在堆栈上自动更新。你能澄清你的误解吗?您不了解代码的输出?您能否提供您得到的结果,因为它在多线程应用程序的情况下可能会有很大不同?
  • 代码运行良好绝对没有问题...我不理解这部分..它在做什么? public void run() { Connection.getInstance().connect(); }

标签: java multithreading


【解决方案1】:

我会试着解释那里发生了什么。由于您将其提交到线程池,因此下面的代码正在每个单独的线程中运行:

public void run() {
    Connection.getInstance().connect();
}

Connection.getInstance() 这里返回一个单例(对象Connection 的单个实例,在线程之间共享,更多:What is an efficient way to implement a singleton pattern in Java?)。这个单例又包含一个信号量,它也是单一的并且在线程之间共享。所以在这种情况下,这种技术的全部目的是在多个线程之间共享一个信号量。

connect() 会发生什么:

public void connect() {
    try {
        // this acquires a single permit for a shared semaphore,
        // so no more than 10 threads (the result of new Semaphore(10, true)) 
        // will enter the critical section below simultaneously
        sem.acquire();
    } catch (InterruptedException e1) {
        e1.printStackTrace();
    }

    try {
        // the critical section, at this point there will be 10 threads at max
        // this is the purpose of the semaphore
        doConnect();
    } finally {
        // returns the permit acquired, so that a one more thread may 
        // enter the critical section
        sem.release();
    }
}

【讨论】:

  • 感谢 Andrey 的建议,我不知道 Singleton。我在网上搜索了一下,现在对它有了一点了解。请您详细说明运行方法 public void run() { Connection.getInstance().connect(); }
  • 我可以将您转至Oracle tutorial。还有一个关于执行者的章节,你可能想看看它。基本上,run() 定义了一个要运行的线程,在这种情况下,这个线程正在一个容器内运行 - 一个线程池。
  • 我明白.. 困扰我的是在 getInstance 中没有名为 connect 的方法。那么这怎么能行呢?抱歉不清楚...
  • getInstance() 是一种返回 Connection 的单例实例的方法 - 声明的静态字段:private static Connection instance = new Connection();。所以connect() 在这个对象上被调用。相当于Connection.instance.connect();
  • 非常感谢您的宝贵时间和建议..我能够得到清晰的图片..需要多练习...
【解决方案2】:

信号量用于获取锁,并执行一些代码最终释放锁。

在您的代码中也发生了同样的事情。

  1. sem.acquire(); 将获得一个锁。
  2. doConnect(); // 在这里写你的代码。
  3. sem.release(); 释放锁。

更多详情请参考this

【讨论】:

  • 能否请您解释一下 Class App 内的 run 方法中发生了什么
猜你喜欢
  • 2012-05-13
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2020-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多