线程管理器Java的多线程实现
我想逐行阅读excel工作表,每行的特定单元格包含URL。我需要通过程序访问该网站来处理这些URL。由于在单线程模型中连续访问每个单元的速度非常慢,因此我计划这样做:线程管理器Java的多线程实现,java,multithreading,Java,Multithreading,我想逐行阅读excel工作表,每行的特定单元格包含URL。我需要通过程序访问该网站来处理这些URL。由于在单线程模型中连续访问每个单元的速度非常慢,因此我计划这样做: Step-1: Read excel sheet's cell of nth row. Step-2: nThreads++ Step-3: if nThreads==MAX_NO_OF_THREADS, sleep till one of the threads is finished. else Instant
Step-1: Read excel sheet's cell of nth row.
Step-2: nThreads++
Step-3: if nThreads==MAX_NO_OF_THREADS, sleep till one of the threads is finished.
else Instantiate a thread to process the URL of that cell.
Step-4: Goto 1.
要实现这一点,我需要以下几点:
1-一些创建线程池的方法。我可以使用线程对象数组进行创建。但是我更喜欢更好的选择
2-一个管理线程,它执行从池中提取线程的任务,处理它们的工作并休眠,直到有一个线程可以执行该任务
那么我有什么选择呢?更容易将其视为限制并发任务的数量。这意味着使用需要输入的可运行项,并且需要知道何时停止运行。此外,您还需要知道所有任务何时完成,以指示所有工作何时完成 我能想到的这个问题的最简单解决方案如下所示
import java.net.URL;
import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
public class Q21512025 {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
try {
new Q21512025(executor, 5).readCells();
} catch (Exception e) {
e.printStackTrace();
}
executor.shutdownNow();
}
private int maxTasks;
private ExecutorService executor;
private CountDownLatch finished;
private LinkedBlockingQueue<ExcellUrlCell> q;
public Q21512025(ExecutorService executor, int maxTasks) {
this.executor = executor;
this.maxTasks = maxTasks;
finished = new CountDownLatch(maxTasks);
q = new LinkedBlockingQueue<ExcellUrlCell>();
}
public void readCells() throws Exception {
for (int i = 0; i < maxTasks; i++) {
executor.execute(new ExcellUrlParser(q, finished));
}
ExcellReader reader = new ExcellReader(getExampleUrls(10));
while (reader.hasNext()) {
q.add(reader.next());
}
for (int i = 0; i < maxTasks; i++) {
q.add(new ExcellUrlCell(null));
}
System.out.println("Awaiting excell url cell tasks.");
finished.await();
System.out.println("Done.");
}
private URL[] getExampleUrls(int amount) throws Exception {
URL[] urls = new URL[amount];
for (int i = 0; i < amount; i++) {
urls[i] = new URL("http://localhost:" + (i + 2000) + "/");
}
return urls;
}
static class ExcellUrlParser implements Runnable {
private CountDownLatch finished;
private LinkedBlockingQueue<ExcellUrlCell> q;
public ExcellUrlParser(LinkedBlockingQueue<ExcellUrlCell> q, CountDownLatch finished) {
this.finished = finished;
this.q = q;
}
@Override
public void run() {
try {
while (true) {
ExcellUrlCell urlCell = q.take();
if (urlCell.isFinished()) {
break;
}
processUrl(urlCell.getUrl());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
finished.countDown();
}
}
private void processUrl(URL url) {
try { Thread.sleep(1); } catch (Exception ignored) {}
System.out.println(url);
}
}
static class ExcellReader implements Iterator<ExcellUrlCell> {
private URL[] urls;
private int index;
public ExcellReader(URL[] urls) {
this.urls = urls;
}
@Override
public boolean hasNext() {
return (index < urls.length);
}
@Override
public ExcellUrlCell next() {
ExcellUrlCell urlCell = new ExcellUrlCell(urls[index]);
index++;
return urlCell;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
static class ExcellUrlCell {
private URL url;
public ExcellUrlCell(URL url) {
this.url = url;
}
public URL getUrl() {
return url;
}
public boolean isFinished() {
return (url == null);
}
}
}
import java.net.URL;
导入java.util.Iterator;
导入java.util.concurrent.CountDownLatch;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.LinkedBlockingQueue;
公共类Q21512025{
公共静态void main(字符串[]args){
ExecutorService executor=Executors.newCachedThreadPool();
试一试{
新Q21512025(executor,5).readCells();
}捕获(例外e){
e、 printStackTrace();
}
执行者。关机现在();
}
私有任务;
私人遗嘱执行人;
私人倒计时结束;
私有链接锁定队列q;
公共Q21512025(执行器服务执行器,int maxTasks){
this.executor=执行人;
this.maxTasks=maxTasks;
完成=新的倒计时锁存器(maxTasks);
q=新的LinkedBlockingQueue();
}
public void readCells()引发异常{
对于(int i=0;i
线程管理器怎么样?我只是碰巧在SourceForge.net上管理了几个Fork/Join服务器。您可以将请求分解为单独的组件,并在单独的线程池中运行每个组件,或者您可以将请求动态分解为相同的任务,以便在线程池中执行
这两种开源产品已经存在多年,可以为您节省很多精力。Use。不要试图自己创建一个池。同步是一件棘手的事情。@zapl酷!但是负责委派任务和等待的管理线程是什么呢?这是一个由参与者建模的完美任务。考虑使用像AKKA这样的事情。@ RAPHW,我宁愿使用标准J2SE UTLS而不是第三方库。这里最大的架构错误是使用同步I/O来获取URL。每个HTTP请求不需要一个线程。请参见
AsyncHttpClient
。