我有一个多线程Java程序,该程序主要与带有代理的Apache HTTP组件一起使用。但是,代码中有一部分与上传照片有关,这占用了相当多的带宽,如果我不限制该部分的并发线程,我将开始超时。现在这就是我所拥有的,它只允许1个线程访问代码部分以上传照片
public class CommonUtil {
private static final Object _uploadPhoto = new Object();
public void start(){
//other code
synchronized (_uploadPhoto) {
//all code related to photo upload
}
//other code
}
}
上面代码的问题是它不考虑链接到该线程的当前代理。我希望我的程序只有在使用同一代理的情况下才能允许线程上传照片。
在程序中,我确实可以检查线程当前正在使用哪个代理
account.getProxyId()
让我们假设我正在使用三个不同的代理服务器。在photoupload部分中,具有不同代理的线程可以使用它,但是如果它们具有相同的代理,则不能。
答案 0 :(得分:1)
使用Java Executors框架为Java的更高版本中内置的concurrency安排任务。参见Tutorial by Oracle。
实例化与代理一样多的线程池支持的执行器。为每个代理跟踪一名执行人。任何特定代理的任务都分配给同一执行程序。
每个执行程序都由其自己的线程池支持,该线程池具有您指定的任何线程限制。当分配的任务数量超过当前可处理的任务数时,执行程序会在线程可用时缓冲它们以分配任务。
提前建立您的执行服务对象,每个代理一个。
ExecutorService execForProxyA = Executors.newFixedThreadPool( 3 ) // Three threads maximum at a time working on tasks headed for proxy "A".
ExecutorService execForProxyB = Executors.newFixedThreadPool( 2 ) // Two threads maximum at a time working on tasks headed for proxy "B".
ExecutorService execForProxyC = Executors.newFixedThreadPool( 5 ) // Five threads maximum at a time working on tasks headed for proxy "C".
定义任务。
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println( "Hello World!" ) ;
}
};
或使用Lambda syntax。
Runnable r = () -> System.out.println( "Hello World!" ) ;
将任务分配给用于所需代理的执行器服务。
您将返回一个Future
对象,该对象可用于跟踪任务的进度和完成情况。
Future future = execForProxyA.submit( r ) ; // Optionally capture the returned `Future` object.
重要:请确保在您的应用中适当关闭执行程序服务。否则,即使在应用退出后,后台线程池的运行时间可能也会比您预期的更长。