关于线程等待的问题,求高手解答

Walkline 2014-02-17 12:11:31
进来分类才发现java分了这么多分类,完全搞不懂,我就说我的问题好了,是jdk 1.3的。。。。。

简单的说,我的程序开新线程去读取网络数据,在读取之前要检查accesstoken的有效性,如果无效,需要在读取数据之前打开一个网页浏览器去进行手动授权,授权成功之后继续后边的读取数据操作,但是我的问题是,在新线程中打开网页浏览器,同时后边的代码也执行了,没有授权也就读取不了数据,程序逻辑上就出问题了,求高手解答一下如何等待网页浏览器关闭后继续后边的操作?

public void refreshAccessToken(boolean force) throws vDiskException
{
synchronized (UiApplication.getEventLock())
{
if (force) // || !isAccessTokenValid()) {
{
setAccessToken(null);
if (Application.isEventDispatchThread())
{
UiApplication.getUiApplication().pushModalScreen(new LoginScreen());
} else {
UiApplication.getApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushModalScreen(new LoginScreen());
}
});
}

if (!hasAccessToken()) {
throw new vDiskException("Unable to refresh the Access Token");
}
}
}
}


在pushModelScreen的同时,就抛出了"Unable to refresh the Access Token"错误
...全文
206 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
raistlic 2014-02-20
  • 打赏
  • 举报
回复
引用 11 楼 Walkline 的回复:
还得麻烦问你一个问题,还是同一个软件,这次是分段上传的,首先打开一个进度窗口,进度窗口调用一个新线程去分割大文件,分割成n段之后用for把每一段上传,上传用的是runnable,上传没有问题,但是我如果想中途中断上传的话,进度窗口调用新线程的stop方法去interrupt去终止线程,但是线程中的runnable不会中断,这个应该怎么处理呢?
interrupt 我没有用过,我一般自设一个flag,不过我在别的地方看到过, 貌似 interrupt 只是一种提醒线程结束的方式,而不是强制线程结束, 需要你自己在 Runnable 内检查 Thread.interrupted() ,比如你用了for循环,大概是这样:


  @Override
  public void run() {
    
    for (<initial>; <condition>; <change>) {
      
      if (Thread.interrupted()) {
        
        // tell progress monitor that progress is interrupted/canceled
        return;
      }

      // tell progress monitor that progress is updated
      // content
    }

    // tell progress monitor that progress is done.
  }

Walkline 2014-02-19
  • 打赏
  • 举报
回复
引用 10 楼 raistlic 的回复:
[quote=引用 7 楼 Walkline 的回复:] 我用的黑莓jdk,最高只支持到1.3,没办法
原来如此,我还以为你是用的某个框架做Swing程序呢…… 不过 event queue 的原理是相通的,模态 (modal) 的定义大概也跟Swing里面差不多 刚刚去翻了一下黑莓的api, 让我始终不太理解的是那个 Application.getEventLock() ,同时也不太理解你在 synchronized(Application.getEventLock()) 里面为什么还要检查 if (Application.isEventDispatchThread()) 总之解决了就好……[/quote] 还得麻烦问你一个问题,还是同一个软件,这次是分段上传的,首先打开一个进度窗口,进度窗口调用一个新线程去分割大文件,分割成n段之后用for把每一段上传,上传用的是runnable,上传没有问题,但是我如果想中途中断上传的话,进度窗口调用新线程的stop方法去interrupt去终止线程,但是线程中的runnable不会中断,这个应该怎么处理呢?
raistlic 2014-02-18
  • 打赏
  • 举报
回复
引用 7 楼 Walkline 的回复:
我用的黑莓jdk,最高只支持到1.3,没办法
原来如此,我还以为你是用的某个框架做Swing程序呢…… 不过 event queue 的原理是相通的,模态 (modal) 的定义大概也跟Swing里面差不多 刚刚去翻了一下黑莓的api, 让我始终不太理解的是那个 Application.getEventLock() ,同时也不太理解你在 synchronized(Application.getEventLock()) 里面为什么还要检查 if (Application.isEventDispatchThread()) 总之解决了就好……
Walkline 2014-02-18
  • 打赏
  • 举报
回复
引用 8 楼 raistlic 的回复:
[quote=引用 5 楼 Walkline 的回复:] 前边还有条件判断呢
条件判断我看到了,如果没有理解错,是为了确保 UiApplication.getUiApplication().pushModalScreen(new LoginScreen()); 这一句总在EDT内执行 new LoginScreen() 必须在EDT内执行可以理解 UiApplication.getUiApplication().pushModalScreen() 也必须在EDT内调用吗? 按上下文你这里需要的大概是同步调用,而 invokeLater 是非同步调用[/quote] 我不行了,你说的太专业了。。。。。这么说吧,所有的invokeLater invokeAndWait之类的都是为了达到目的而做的尝试,没有什么意图,只是为了实现目的。。。。。
raistlic 2014-02-18
  • 打赏
  • 举报
回复
引用 5 楼 Walkline 的回复:
前边还有条件判断呢
条件判断我看到了,如果没有理解错,是为了确保 UiApplication.getUiApplication().pushModalScreen(new LoginScreen()); 这一句总在EDT内执行 new LoginScreen() 必须在EDT内执行可以理解 UiApplication.getUiApplication().pushModalScreen() 也必须在EDT内调用吗? 按上下文你这里需要的大概是同步调用,而 invokeLater 是非同步调用
Walkline 2014-02-18
  • 打赏
  • 举报
回复
引用 2 楼 raistlic 的回复:
在不知道1楼所说的这些东西的情况下, 我猜你的问题情况是:调用来自非EDT线程,invokeLater之后直接检查导致失败, 能给你的最好的建议就是看看 UiApplication.getApplication() 有没有 invokeAndWait 方法,我猜UiApplication.getApplication()是个单例,并且对 SwingUtilities/EventQueue 的一些方法作了封装 原代码第 14 行:

public void refreshAccessToken(boolean force) throws vDiskException
    {
        synchronized (UiApplication.getEventLock())
        {
            if (force) // || !isAccessTokenValid()) {
            {
                setAccessToken(null);
                if (Application.isEventDispatchThread())
                {
                    UiApplication.getUiApplication().pushModalScreen(new LoginScreen());
                } else {
                    UiApplication.getApplication().invokeAndWait(new Runnable() {
                        public void run() {
                            UiApplication.getUiApplication().pushModalScreen(new LoginScreen());
                        }
                    });
                    // 可能会有 checked exception 需要处理
                }
 
                if (!hasAccessToken()) {
                    throw new vDiskException("Unable to refresh the Access Token");
                }
            }
        }
    }
如果这样改导致死锁,那可能是因为我对 synchronized (UiApplication.getEventLock()) 不了解,并且你这部分的线程设计可能有问题。
谢谢你的回复,看的我云里雾里的,都是专业术语,我用的黑莓jdk,最高只支持到1.3,没办法 不过问题我已经解决了,在调用refreshAccessToken()的函数里加锁,然后在refreshAccessToken()里解锁,就是在pushModelScreen返回之后,就搞定了
synchronized (ACCESS_TOKEN_LOCK) {
			if (!hasAccessToken())
			{
				refreshAccessToken(true);
				try {
					ACCESS_TOKEN_LOCK.wait(vDiskConfig.AUTHORIZE_TIMEDOUT);
				} catch (InterruptedException e) {}
			}
		}
我的要求就是必须等LoginScreen返回之后才能继续后边的操作,不能同步执行。。。。。我对这个多线程不是很明白,所以代码有些莫名其妙,见笑了
raistlic 2014-02-18
  • 打赏
  • 举报
回复
引用 5 楼 Walkline 的回复:
[quote=引用 4 楼 raistlic 的回复:] 如果 UiApplication.getUiApplication().pushModalScreen() 可以在任何线程调用, 并且正确运用了【模态】, 那你不应该用 invokeLater 把它包起来
不是的,前边还有条件判断呢,Application.isEventDispatchThread(),app初始化后就会调用这个push窗口,但是app并没有enterEventDispatcher,所以要先挂起排到队列里[/quote] 完全搞不懂你在说什么,能不能叙述得更有条理一些……
Walkline 2014-02-18
  • 打赏
  • 举报
回复
引用 4 楼 raistlic 的回复:
如果 UiApplication.getUiApplication().pushModalScreen() 可以在任何线程调用, 并且正确运用了【模态】, 那你不应该用 invokeLater 把它包起来
不是的,前边还有条件判断呢,Application.isEventDispatchThread(),app初始化后就会调用这个push窗口,但是app并没有enterEventDispatcher,所以要先挂起排到队列里
raistlic 2014-02-18
  • 打赏
  • 举报
回复
如果 UiApplication.getUiApplication().pushModalScreen() 可以在任何线程调用, 并且正确运用了【模态】, 那你不应该用 invokeLater 把它包起来
地下室森林 2014-02-18
  • 打赏
  • 举报
回复
那个锁的位置不是应该放在下面吗?
raistlic 2014-02-18
  • 打赏
  • 举报
回复
在不知道1楼所说的这些东西的情况下, 我猜你的问题情况是:调用来自非EDT线程,invokeLater之后直接检查导致失败, 能给你的最好的建议就是看看 UiApplication.getApplication() 有没有 invokeAndWait 方法,我猜UiApplication.getApplication()是个单例,并且对 SwingUtilities/EventQueue 的一些方法作了封装 原代码第 14 行:

public void refreshAccessToken(boolean force) throws vDiskException
    {
        synchronized (UiApplication.getEventLock())
        {
            if (force) // || !isAccessTokenValid()) {
            {
                setAccessToken(null);
                if (Application.isEventDispatchThread())
                {
                    UiApplication.getUiApplication().pushModalScreen(new LoginScreen());
                } else {
                    UiApplication.getApplication().invokeAndWait(new Runnable() {
                        public void run() {
                            UiApplication.getUiApplication().pushModalScreen(new LoginScreen());
                        }
                    });
                    // 可能会有 checked exception 需要处理
                }
 
                if (!hasAccessToken()) {
                    throw new vDiskException("Unable to refresh the Access Token");
                }
            }
        }
    }
如果这样改导致死锁,那可能是因为我对 synchronized (UiApplication.getEventLock()) 不了解,并且你这部分的线程设计可能有问题。
raistlic 2014-02-18
  • 打赏
  • 举报
回复
一定要用 1.3 ? 是 Swing 程序吗? 1.3 的模态 (modal) 是怎样工作的,不太清楚…… 另外: 1 - 这个方法是在哪个线程调用的? 有没有可能是 EDT? 2 - 有没有要求方法必须是同步执行,即方法确保工作完成以后才返回? 3 - 那个 synchronized (UiApplication.getEventLock())是要确保什么?

62,615

社区成员

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

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