0

不幸的是,我对如何正确设置线程的理解非常糟糕。我知道在 SO.SE 和其他网站上都有大量关于此的信息,但我似乎无法将我正确阅读的内容与我正在做的事情联系起来。

我的问题是我有一种方法,它采用两个参数,其中一个参数除以另一个参数。商(结果)用于填充可视进度条。当商达到 1, 时(readBytes/contentLength == 1),我希望某个线程(我猜)在从布局中删除进度条之前等待给定时间。我知道将值设置为进度条所需的所有代码以及如何将其从视图中删除,我的问题是如何让它等待,例如,在触发操作以删除组件之前等待 2000 毫秒?

这可能是基本的线程知识,但我遇到了很大的问题。

到目前为止,我已经尝试了这两种方法:

@Override
    public void updateProgress(long readBytes, long contentLength) {

        this.contentLength = contentLength;

        if(readBytes != 0 && contentLength != 0 && fileListItem != null)    {

            fileListItem.getProgressIndicator().setValue(readBytes/contentLength);

            synchronized (this) {
                while(readBytes/contentLength != 1) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    };
                    fileListItem.removeProgressIndicator();                 
                }
            }
        }

        if(!itemIsAdded)    {

            checkFileCompatibility(contentLength);

        }
    }

@Override
    public void updateProgress(long readBytes, long contentLength) {

        this.contentLength = contentLength;

        if(readBytes != 0 && contentLength != 0 && fileListItem != null)    {

            if(readBytes/contentLength == 1)    {
                Thread t = new Thread();
                t.start();
                try {
                    t.wait(2000);
                    fileListItem.removeProgressIndicator();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                t.interrupt();
            } else  {
                fileListItem.getProgressIndicator().setValue(readBytes/contentLength);
            }
        }

        if(!itemIsAdded)    {

            checkFileCompatibility(contentLength);

        }
    }

没有成功。在第一个示例中,主线程似乎是等待的线程,没有任何反应。在第二个示例中,我在t.wait(2000);. 我不知道该怎么做。。

编辑:根据 Bohemian 的意见,我得到了它的工作。

@Override
    public void updateProgress(final long readBytes, final long contentLength) {

        this.contentLength = contentLength;

        if(readBytes != 0 && contentLength != 0 && fileListItem != null)    {

            if(!threadIsRunning)    {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        threadIsRunning = true;
                        while(!fileIsAdded) {
                            try {
                                Thread.sleep(2000);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                LOGGER.error(e.getMessage());
                                break;
                            }
                        }
                        fileListItem.removeProgressIndicator();
                        threadIsRunning = false;
                    }
                }).start();
            }

            fileListItem.getProgressIndicator().setValue(readBytes/contentLength);
            if(readBytes == contentLength)
                fileIsAdded = true;
        }

        if(!itemIsAdded)    {

            checkFileCompatibility(contentLength);

        }
    }

它仍然需要一些整理,但基础现在正在工作!

4

3 回答 3

2

SwingWorker很可能是适合您任务的工具。Javadoc 中有完整的代码示例。注意方法setProgress——这是更新进度条的理想选择。

如果您真正需要的只是清除进度条的固定 2 秒延迟,那么您想使用Swing Timer。它甚至不涉及多线程,您只需编写一个回调处理程序,该处理程序将在指定的延迟后执行。

于 2012-06-28T11:05:05.057 回答
1

我认为你真正需要的是

Thread.sleep(2000);

而不是wait. 虽然wait可以用于睡眠,但它的主要功能是用于线程间信号,并且需要锁定正在等待的对象,而您尚未获得该锁定,因此出现异常。

编辑:经过进一步检查,我注意到您做事不正确。您只是在创建一个没有关联run方法的线程:

Thread t = new Thread();
t.start();

因此,您的线程没有执行任何操作。

我建议阅读有关如何正确设置线程的 Java 线程教程:http: //docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

于 2012-06-28T10:28:33.587 回答
1

我不会让主线程等待。这是不好的做法,因为它不可扩展并且会使您的 GUI 紧张。

相反,我会将超时值和几个回调传递给工作线程,以在它超过超时/完成工作时执行。这样主线程就可以自由地回去做它想做的任何事情。

仅出于说明目的,您的“完成”回调可能如下所示:

new Runnable() {
    public void run() {
        // code that hides the progress bar
    }
}

您的“超时”回调可能如下所示:

new Runnable() {
    public void run() {
        // code that displays an error message
    }
}

顺便说一句,要让线程做某事,您还可以传递一个 Runnable:

new Thread(new Runnable() {
    public void run() {
        // code that runs when your thread starts
    }
}).start();
于 2012-06-28T10:31:25.543 回答