信号量 - 为什么我的线程一个接一个地 运行 而不是并发?
Semaphore - why my threads are running one after the other and not in concurrent?
我正在尝试编写一个程序,在 Main
class 中可以启动未知数量的新线程。
每个线程依次调用 Singleton Copier
class 应该调用文件传输操作。
我的目标是,无论线程请求的数量如何,限制 并发传输数为 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
class:
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..
如果你调用Thread.run()
你不启动线程,你只是按顺序执行方法。您需要致电 start()
。 (我假设 CopyThread
是 Thread
)。
Java Joshua Bloch 的 Puzzlers 有一章有一个非常相似的例子。
你应该调用 start()
而不是 run()
否则它不会启动你的线程,这样传输将按顺序完成,这实际上是你当前问题的根本原因。
无论如何,对我来说你的代码应该被重写为 class 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。正确实现CopyThread
的方法run()
@Override
public void run() {
// Here I call fileTransfer() on Copier instead of the other way around
Copier.getInstance().fileTransfer();
}
3。使 semaphore
非静态和最终
private final Semaphore semaphore;
private Copier() {
this.semaphore = new Semaphore(POOL_SIZE);
}
4。使用内部 class 来延迟创建您的实例
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..
我正在尝试编写一个程序,在 Main
class 中可以启动未知数量的新线程。
每个线程依次调用 Singleton Copier
class 应该调用文件传输操作。
我的目标是,无论线程请求的数量如何,限制 并发传输数为 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
class:
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..
如果你调用Thread.run()
你不启动线程,你只是按顺序执行方法。您需要致电 start()
。 (我假设 CopyThread
是 Thread
)。
Java Joshua Bloch 的 Puzzlers 有一章有一个非常相似的例子。
你应该调用 start()
而不是 run()
否则它不会启动你的线程,这样传输将按顺序完成,这实际上是你当前问题的根本原因。
无论如何,对我来说你的代码应该被重写为 class 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。正确实现CopyThread
的方法run()
@Override
public void run() {
// Here I call fileTransfer() on Copier instead of the other way around
Copier.getInstance().fileTransfer();
}
3。使 semaphore
非静态和最终
private final Semaphore semaphore;
private Copier() {
this.semaphore = new Semaphore(POOL_SIZE);
}
4。使用内部 class 来延迟创建您的实例
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..