初学java,请教多线程通信问题!

hjjdebug 2010-03-22 04:35:37
问题提出:
我编写的一个网页下载程序,网页下载中,有可能会断线而下载不成功。
所以可以启动一个定时器,定时器到还没有下载成功,需要重新下载该网页。
若在定时内下载成功,则可以下载另一个网页。

程序流程如下,
主线程用来启动读网页线程,并启动定时器。然后等待读网页线程的完成。
如果定时器超时,则杀死或中断读线程,重新读该网页。如果读网页成功,则cancel 掉此定时器,
进入下一循环,读下一个网页。

但碰到了如下问题。
1. 如果主线程等待读线程,(用join()) 则主线程就会阻塞。 怎样接受定时器
溢出消息。即定时器超时后,怎样通知主线程。

2. 如果主线程不阻塞,而是循环查询一个定时器设定的溢出标志。那读线程结束了
又怎样通知主线程, 当然,可以再设另一标志,让主线程一块查。这样主
线程就知道是定时器先溢出,还是读线程先结束。 不过我想这可能是最笨的
办法了。要想使用变量通信,还得将定时器,读线程设置成内部类。
我想java 一定有处理此类问题的好办法。还请java 高手不吝赐教!在此先感谢了!!

附我整理的针对此问题的代码帮助分析:请高手重点关注一下带???的三条语句

import java.io.*;
import java.net.*;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Timer;
import java.util.TimerTask;

public class TestGetHtml {

public static void main(String[] args) throws IOException {

// while(获取下一个连接,直到所有链接处理完毕,此处忽略){
String urllink1 = "http://www.baidu.com"; // for test only
while(true) //读取网页,指导成功为止
{
// 启动读线程
Thread thread = new MyReadThread(urllink1);
thread.start();
// 启动定时器, 我不知道定时器怎样通知主线程 ????????????
MyTimer timer = new MyTimer(1000); //设定超时时间,自己调整测试
timer.start();
// 等待读线程
try{
thread.join(); // 用join 等待可能不太好吧,但我不知道用什么方法。 ???????????
}
catch(InterruptedException e)
{
e.printStackTrace();
}
// 如果定时器超时,主线程要重新执行该循环,但我不知主线程怎样接受定时器消息 ?????????
// 如果读网页成功,则cancel 定时器,
System.out.println("Read html OK");
timer.stop();
break; //正常结束了,可以退出循环
}
// 忽略}
}
}

class MyReadThread extends Thread
{

private static String urlName;
private static URL url;
private static URLConnection connection;
private static String type;
MyReadThread(String s)
{
urlName = s;
type = null;
url = null;
connection = null;
}
@Override
public void run()
{
System.out.println("connentting...");
connect(urlName);
System.out.println("reading...");
readContents();
}

static void connect( String urlString ) {
try {
url = new URL(urlString);
connection = url.openConnection();
//System.out.println(connection.getClass());
} catch (MalformedURLException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}


static void readContents() {
BufferedReader reader = null;
try {
reader = new BufferedReader( new InputStreamReader( connection.getInputStream()));
String inputLine;
while ( (inputLine = reader.readLine()) != null)
{
System.out.println(inputLine);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

class MyTimer
{
int miliseconds;
Timer timer;
MyTimer(int miliseconds)
{
this.miliseconds = miliseconds;
}
public void start()
{
class MyTimerTask extends TimerTask{
@Override
public void run()
{
System.out.println("ha ha! time over .... reconnecting ...");
timer.cancel();
}
}
timer = new Timer();
timer.schedule(new MyTimerTask(), miliseconds);
System.out.println("start timer "+miliseconds);
}
public void stop()
{
// System.out.println("want stop timer");
timer.cancel(); // when has receive ok
}
}


...全文
143 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
hjjdebug 2010-03-23
  • 打赏
  • 举报
回复
问题已经解决,帖子掉的真快啊!
使用wait ,notify notifyAll,及共享数据已经解决。
谢谢各位参与,分分。为保证信息完整,我把shareobject 代码贴出来

class ShareObject
{
private boolean timeover;
private boolean readhtmlok;
ShareObject()
{
timeover = false;
readhtmlok = false;
}
public synchronized void TimerOver()
{
timeover = true;
notifyAll(); // 通知已经设好
}
public synchronized void ReadHtmlOK()
{
readhtmlok = true;
notifyAll(); // 通知已经设好
}

public synchronized boolean GetReadResult()
{
if((timeover == false) && (readhtmlok == false))
{
try{
wait(); //等待完成
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
if(readhtmlok == true)
{
return true;
}
else if(timeover == true)
{
return false; //read time over
}
else
{
System.out.println("I don't think will got here!");
}
return false;
}
}
hjjdebug 2010-03-22
  • 打赏
  • 举报
回复
是不是可以用生产者,消费者来解决问题,
这里定时器是一个生产者,下载进程也是一个生产者,主线程是消费者。
只不过生产者只生产一次,即功成身退。 消费者也只消费一次。
小小问题,搞的这么复杂, 有没有别的好办法呢 ?
回头试试生产者,消费者... 大家继续啊,贴代码最好!
hjjdebug 2010-03-22
  • 打赏
  • 举报
回复
我的理解,java 定时器也是一个特殊的线程。 放到下载线程中也行,下载线程可能会被阻塞而超时。
但超时的结果必需要通知主线程。反正主线程要知道是下载成功了还是超时了。我不知道主线程应该怎样知道。
要是用C++ 就简单了。
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);

根据返回值可以知道是WAIT_OBJECT_0, 或者WAIT_TIMEOUT。 但这里是java ,我不得,继续....
jimyx123 2010-03-22
  • 打赏
  • 举报
回复
主线程就不要堵塞了吧,可否把定时器作为构造参数传给下载线程
由下载线程去控制打开,出现异常就直接检查定时器状态 决定重试还是放弃
同时要控制好线程数量,JAVA的连接 共享端口不怎么好用,容易出现无法分配端口
jcqhaha 2010-03-22
  • 打赏
  • 举报
回复
茫茫。。。。。。。。。。。。。。
justwalking 2010-03-22
  • 打赏
  • 举报
回复
顶帖。。。。。。。。。。。。。。。。。。。。

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧