我想写一个多个线程并发的爬虫,获取网页中的某张图片,使用的HttpClient的MultiThreadedHttpConnectionManager,功能实现类继承Thread类,参考了http://topic.csdn.net/u/20071108/14/252592ED-21DD-433A-9C2E-3EEB8D8CE686.html的方法写了http类,现在问题是运行到一定程度会出现死锁,测试过将Thread中get方法注释掉则可以正常运行,推断有可能是httpclient的问题,但是看不出问题在哪。另外我的程序中会新建几千个进程,有时出现内存溢出,不知是否有其他更好的实现方式?Thread类
public class ProcessRemotePic extends Thread {
// http://quanta.11tea.com/blog/6577 Java多线程(线程池管理)下载网页上的所有图片(Img标签)程序
private HttpClient client;
private String url;
private String dst;
private String picName;
private String picPrefix;
private String pattern;
private LockClass lock; public ProcessRemotePic(HttpClient client, String url, String dst,
String picName, String picPrefix, String pattern, String lock) {
this.lock = LockClass.getLock(lock);
this.url = url;
this.client = client;
this.dst = dst;
this.pattern = pattern;
this.picName = picName;
this.picPrefix = picPrefix;

}
public void run(){
lock.lock();
System.out.println("运行中");
get();
System.out.println("运行结束");
lock.unlock();
}
@SuppressWarnings("unused")
public void get() {
NodeList nlist = null;
DOMParser parser = new DOMParser();
String picPath = null; HttpMethod get = new GetMethod(url);
get.setFollowRedirects(false);
try {
if (client.executeMethod(get) == HttpStatus.SC_OK) {
parser.parse(url);
nlist = parser.getDocument().getElementsByTagName("img");
for (int j = 0; j < nlist.getLength(); j++) {
if (nlist.item(j).getAttributes().getNamedItem("src")
.getNodeValue().toString().indexOf(pattern) != -1) {
picPath = picPrefix
+ nlist.item(j).getAttributes().getNamedItem(
"src").getNodeValue().toString();
System.out.print("pathOK");
// System.out.print(j);
// get.releaseConnection();
break;
}
} get = new GetMethod(picPath);

//System.out.print(picPath);
client.executeMethod(get);
// System.out.print("200"); File storeFile = new File(dst + picName);
FileOutputStream output = new FileOutputStream(storeFile);
output.write(get.getResponseBody());
output.close();
System.out.println("saveOK"); } else {
System.out.println("Error:" + get.getStatusCode());
return;
} } catch (Exception e) {
e.printStackTrace();
} finally {
get.releaseConnection();
}
} @SuppressWarnings("unused")
public int delPic(String picPath) { File Pic = new File(picPath);
try {
if (!Pic.exists()) {
return -1;
} else {
Pic.delete();
// System.out.print("del");
}
} catch (Exception e) {
e.printStackTrace();
}
return 1;
} public static int getPosition(String filepath) {
int i = 100;
try {
Properties property = new Properties(); property.load(new FileInputStream(filepath)); i = Integer.parseInt(property.getProperty("position")); } catch (Exception e) {
e.printStackTrace();
}
return i;
} public static void setPosition(String position, String filepath) {
try {
Properties property = new Properties(); property.setProperty("position", position);
property.store(new FileOutputStream(filepath), "update");
} catch (Exception e) {
e.printStackTrace();
}
}
}class LockClass {
private static HashMap hm = new HashMap();
private String str; private LockClass(String str) {
this.str = str;
} // 多例模式
public  static LockClass getLock(String str) {
LockClass lc = (LockClass) hm.get(str);
if (lc == null) {
lc = new LockClass(str);
hm.put(str, lc);
} return lc;
} private boolean isUsed = false; public synchronized void lock() {
if (isUsed) {
try {
wait();
} catch (InterruptedException ex) {
System.out.println(ex);
} }
isUsed = true;
System.out.println("锁定中");
} public synchronized void unlock() {
isUsed = false;
notify();
System.out.println("释放完了");
}}主程序运行类
public class GetPic {
// http://blog.csdn.net/cozmic/archive/2005/08/16/455584.aspx public static void main(String args[]) throws Exception {
// Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// String dburl ="jdbc:odbc:driver={Microsoft Access Driver
// (*.mdb)};DBQ=Mobile.mdb";//此为NO-DSN方式
String dburl = "jdbc:odbc:mysql-yz";// 此为ODBC连接方式
List<String> JD = new ArrayList();
List<String> NE = new ArrayList();
Http http = Http.getInstance();
HttpClient client = http.getClient();
int jdLength = 0;
int neLength = 0; DriverManager.registerDriver(new JdbcOdbcDriver());
Connection conn = DriverManager.getConnection(dburl);
Statement stmt = conn.createStatement();
ResultSet rs = null;
try {
rs = stmt
.executeQuery("select * from tb_compare order by icson_id asc");
while (rs.next()) {
if (rs.getInt(3) == 1) {
JD.add(rs.getString(2));
jdLength++;
} else {
continue;
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
rs.close();
stmt.close();
conn.close();
} Iterator jd = JD.iterator();

ProcessRemotePic[] jdthreads = new ProcessRemotePic[jdLength];

for (int i = 0; i < jdLength; i++) {
String itr = (String) jd.next();
//System.out.print(itr);
jdthreads[i] = new ProcessRemotePic(argv,i % 5 + "");
jdthreads[i].start();
}
System.out.print("OK");
// MultiThreadedHttpConnectionManager.shutdownAll();
}}

解决方案 »

  1.   

    用过lucene,爬虫没怎么弄过,呵呵,顶下。
      

  2.   

    lz试试改成:
    public synchronized void lock() {
            while (isUsed) {
                try {
                    wait();
                } catch (InterruptedException ex) {
                    System.out.println(ex);
                    throw new RuntimeException(ex);
                }
            }
            isUsed = true;
            System.out.println("锁定中");
        }    public synchronized void unlock() {
            isUsed = false;
            notifyAll();
            System.out.println("释放完了");
        }
      

  3.   

    3楼的兄弟,改了试过了,死的更快,而且没有异常抛出,我估计可能是HttpClient的问题,但是网上HttpClient的资料太少,我也不太会调试,能指教一下吗,或者我把代码发给你帮我看看。