java - 信号量 - 为什么我的线程一个接一个地运行而不是并发运行?

标签 java multithreading concurrency semaphore

我正在尝试编写一个程序,在 Main 类中可以启动未知数量的新线程。 每个线程依次调用 Singleton Copier 类,该类应调用文件传输操作。

我的目标是,无论线程请求的数量如何,都是将并发传输的数量限制为 2 个传输,所以我想用 Semaphore 来解决它。 我的问题是,线程似乎一个接一个地运行,而不是并发运行。

这是我尝试做的:

public class Copier {

    private static final int POOL_SIZE = 2;
    private static volatile Copier instance = null;
    private static Semaphore semaphore;

    private Copier() {

    }

    public static Copier getInstance() {
        if (instance == null) {
            synchronized (Copier.class) {
                if (instance == null) {
                    instance = new Copier();
                    semaphore = new Semaphore(POOL_SIZE);
                }
            }
        }
        return instance;
    }

    public void fileTransfer(CopyThread copyThread) {
        try {
            semaphore.acquire();
            System.out.println("Running thread...");
            copyThread.run();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        finally {
            semaphore.release();
            System.out.println("Thread released..");
        }
    }
}

这是我的 Main 类:

public class Driver {
    public static void main(String[] args) {
        Copier copier = Copier.getInstance();
        CopyThread copyThread1 = new CopyThread();
        CopyThread copyThread2 = new CopyThread();

        copier.fileTransfer(copyThread1);
        copier.fileTransfer(copyThread2);
    }
}

运行它时 - 您可以通过输出看到线程一个接一个地运行,而我的目的是最多有 2 个并发线程。 我做错了什么?

Running thread...
3.998784MB were transferred in 5.902514932 seconds
Thread released..
Running thread...
4.062673MB were transferred in 7.199550077 seconds
Thread released..

最佳答案

你应该调用 start() 而不是 run() 否则它不会启动你的线程,这样传输将按顺序完成,这实际上是当前问题的根本原因。

无论如何,对我来说,您的代码应该被重写为 Copier 类甚至不应该 start() 线程,因为这不是它的职责。

1。重写方法 fileTransfer()

public void fileTransfer() {
    try {
        semaphore.acquire();
        System.out.println("Running transfer...");
        // Code that performs the transfer
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        semaphore.release();
        System.out.println("Thread released..");
    }
}

2。正确实现CopyThreadrun()方法

@Override
public void run() {
    // Here I call fileTransfer() on Copier instead of the other way around
    Copier.getInstance().fileTransfer();
}

3。使信号量非静态和最终

private final Semaphore semaphore;

private Copier() {
    this.semaphore = new Semaphore(POOL_SIZE);
}

4。使用内部类来延迟创建您的实例

public class Copier {
    ...
    public static Copier getInstance() {
        return Holder.instance;
    }
    ...
    private static class Holder {
        private static final Copier instance = new Copier();
    }
}

5。重写你的 main 方法

public static void main(String[] args) throws Exception {
    CopyThread copyThread1 = new CopyThread();
    CopyThread copyThread2 = new CopyThread();

    copyThread1.start();
    copyThread2.start();
}

输出:

Running transfer...
Running transfer...
Thread released..
Thread released..

关于java - 信号量 - 为什么我的线程一个接一个地运行而不是并发运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39609913/

相关文章:

c# - 如何优雅地停止 System.Threading.Timer?

java - 当框架是Hybrid并且测试用例由Selenium中的excel驱动时,如何使用TestNG注释?

python - 限制numpy中的线程数

c++ - std::async 有什么问题?

java - 无论线程如何,对象是否总是看到其最新的内部状态?

java - final 字段如何防止其他线程看到部分构造的对象?

java - Java 中的 CSS 解析器

java - 在Java中重写equals和hashCode时应该考虑哪些问题?

java - 接收数据报包不显示

java - 如何在单线程中执行OSGI包的激活和停用方法