我已经实现了一个应用程序,将文件从服务器机器FTP到客户端机器
for(String sourceFolder : foldersPaths){
transferFolder(channelSftp,SFTPWORKINGDIR+sourceFolder,
DESWORKINGDIR+sourceFolder.replace("/","\"));
}
这段代码遍历字符串的 ArrayList 具有我需要传输的每个文件的源路径。我正在考虑利用带宽并同时为不同的文件启动多个传输。
如何创建同时执行"传输文件夹"方法的不同线程。是否可以安全,以便同一项目不会在不同的线程中循环两次。
谢谢
你可以有一个 ArrayBlockingQueue 来保存你的 URI,并让它安全地在池中的线程之间共享以执行。
Set<String> submitted = Collections.synchronizedSet(new HashSet<String>());
ExecutorService executorService = Executors.newFixedThreadPool(10); // how many threads to work with it
for(final String sourceFolder : foldersPaths){
if(! submitted.contains(sourceFolder)) {
Runnable runnable = new Runnable() {
@Override
public void run() {
transferFolder(...); // your method invoked here
}
};
if (submitted.add(sourceFolder)) {
executorService.submit(runnable);
}
}
}
executorService.shutdown();
问题不在于循环,而在于突变。如果你的List
是不可变的,你可以根据需要从中读取尽可能多的Thread
。
但是,如果要从此List
中删除/添加,则需要执行一些同步,或者必须使用并发数据结构。后者是我推荐的。对于您的情况,CopyOnWriteArrayList
可能会解决问题。
如果您需要类似队列的数据结构,则可以使用例如LinkedBlockingQueue
。
方法 1 :
队列数据结构最适合此操作。从队列中获取文件时获取锁,然后在完成后释放锁。应使用相同的对象来授予跨所有线程的队列的访问权限。
while(!queue.isEmpty())
{
synchronized(lockingObject) /// Get the lock for mutual access to Queue
{
String file = queue.dequeue();
}
// lock is released
}