我正在尝试编写一个程序,在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);
}
}
运行它时 - 您可以通过输出看到一个接一个地运行的线程,而我的目的是最多有两个并发线程。 我做错了什么?
Running thread...
3.998784MB were transferred in 5.902514932 seconds
Thread released..
Running thread...
4.062673MB were transferred in 7.199550077 seconds
Thread released..
答案 0 :(得分:2)
您应该拨打start()
而不是run()
,否则它将无法启动您的线程,以便顺序完成转移,这实际上是您当前问题的根本原因。< / p>
无论如何,对我来说,你的代码应该被重写,因为类Copier
甚至不应该开始()线程,因为它不是它的职责。
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..");
}
}
run()
方法CopyThread
@Override
public void run() {
// Here I call fileTransfer() on Copier instead of the other way around
Copier.getInstance().fileTransfer();
}
semaphore
非静态和最终private final Semaphore semaphore;
private Copier() {
this.semaphore = new Semaphore(POOL_SIZE);
}
public class Copier {
...
public static Copier getInstance() {
return Holder.instance;
}
...
private static class Holder {
private static final Copier instance = new Copier();
}
}
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..
答案 1 :(得分:1)
如果你打电话给Thread.run()
你没有启动线程,你只需按顺序执行该方法。您需要致电start()
。 (我假设CopyThread
是Thread
)。
Joshua Bloch的Java Puzzlers有一章有一个非常相似的例子。