Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何知道线程是否在SWT环境中完成了任务?_Java_Multithreading_Swt - Fatal编程技术网

Java 如何知道线程是否在SWT环境中完成了任务?

Java 如何知道线程是否在SWT环境中完成了任务?,java,multithreading,swt,Java,Multithreading,Swt,我很难从一些线程中得到结果。 我解释了环境,我有一个带按钮的SWT外壳。此按钮的侦听器调用一个Runnable,该Runnable在其run()内调用一个实例化N个线程以执行某些操作的方法。问题是:当所有计算都终止时,如何在屏幕上显示消息对话框或其他内容?我的代码是类似的 public void widgetSelected(SelectionEvent event) { Runnable t = new MyThread(params); executor.execute(t)

我很难从一些线程中得到结果。 我解释了环境,我有一个带按钮的SWT外壳。此按钮的侦听器调用一个Runnable,该Runnable在其run()内调用一个实例化N个线程以执行某些操作的方法。问题是:当所有计算都终止时,如何在屏幕上显示消息对话框或其他内容?我的代码是类似的

public void widgetSelected(SelectionEvent event) {
    Runnable t = new MyThread(params);
    executor.execute(t);
  }
我在MyThread班上

public void run(){
   myMethod();
}

public void myMethod(){
   for(int i =0; i<queue.length; i++){
      Runnable thread = new AnotherThread();
      executor.execute(thread);
   }
   executor.shutdown();
   if(executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS){
     //here I know all thread of kind AnotherThread have finished
   }
}
public void run(){
myMethod();
}
公共方法(){
对于(inti=0;i这是“直截了当的”-但需要做一点工作:您“只是”必须增强您的Runnable,以某种方式显示它们的进度

换句话说:ExecutorService接口不提供任何方法来计算计划的“任务”完成了多少。因此,如果您需要这些信息,您必须将其“烘焙”到您的Runnable中

一个想法是:预先创建一个
Map
。键是您的可运行对象,值可以表示一些进度信息。您从0开始所有值。然后将该映射传递给每个可运行对象,可运行对象只需在特定的定义时间点更新其值。可能需要十个步骤,也可能只有4个步骤。并且在所有步骤完成后尽快更新地图值为100,您知道您已经完成了!这意味着您的主线程只是每隔一秒/分钟/循环并检查地图内容……当然:这个额外的线程应该而不是作为事件调度线程。您不想在执行此操作时暂停UI

(当然:您应该使用ConcurrentHashMap来实现这一点)


长话短说:这些信息已经可用-Runnable中的代码知道它在做什么,对吧?!所以你“只”必须以某种方式使外部世界能够访问这些信息。有很多方法可以做到这一点;以上只是实现这一点的一种方法。

我建议您看看如何使用Guava库的一部分

这将允许您为您启动的每个任务创建一个。在您的情况下,这听起来像是由一个
可运行的
表示的,但您也可以轻松地使用一个
可调用的
。当这些任务全部启动后,您将得到一个可以“展平”为单个
ListenableFuture
,表示所有任务的完成。这通过以下方法完成:

现在,一旦这些任务完成,我们需要更新UI以通知用户。为此,我们必须确保UI更新发生在SWT UI线程上:

Display.getCurrent().asyncExec(new Runnable() {
    @Override
    public void run() {
        // Update the UI
    }
});
请注意,这可以在上面的onSuccess()方法中轻松完成,以便使用任务的结果

综上所述,我们可以轻松地循环执行少量.submit(…)后台执行调用(这样就不会阻塞UI线程-在我下面的示例中,当任务在后台运行时,您可以自由地在文本框中键入),抓取所有的
ListenableFutures
,并添加一个在完成时调用的回调,该回调将跳回UI线程以进行UI更新


完整示例:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

public class CallbackExample {

    private final Display display;
    private final Shell shell;
    private final Text output;
    private final ListeningExecutorService executor;

    public CallbackExample() {
        display = new Display();
        shell = new Shell(display);
        shell.setLayout(new FillLayout());

        executor = MoreExecutors.listeningDecorator(Executors
                .newFixedThreadPool(20));

        final Composite baseComposite = new Composite(shell, SWT.NONE);
        baseComposite
                .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        baseComposite.setLayout(new GridLayout());

        output = new Text(baseComposite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
        output.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        final Button button = new Button(baseComposite, SWT.PUSH);
        button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        button.setText("Start tasks");
        button.addSelectionListener(new SelectionAdapter() {

            @SuppressWarnings("synthetic-access")
            @Override
            public void widgetSelected(final SelectionEvent e) {
                // Start tasks when the button is clicked
                startTasks();
            }

        });

    }

    private void startTasks() {
        // Create a List to hold the ListenableFutures for the tasks
        final List<ListenableFuture<String>> futures = new ArrayList<ListenableFuture<String>>();
        // Submit all the tasks for execution (in this case 100)
        for (int i = 0; i < 100; i++) {
            final ListenableFuture<String> future = executor
                    .submit(new Callable<String>() {
                        @Override
                        public String call() throws Exception {
                            // Do the work! Here we sleep to simulate a long task
                            Thread.sleep(2000);
                            final long currentMillis = System
                                    .currentTimeMillis();
                            System.out.println("Task complete at "
                                    + currentMillis);
                            return "Task complete at " + currentMillis;
                        }
                    });
            // Add the future for this task to the list
            futures.add(future);
        }
        // Combine all of the futures into a single one that we can wait on
        final ListenableFuture<List<String>> future = Futures
                .allAsList(futures);
        // Add the callback for execution upon completion of ALL tasks
        Futures.addCallback(future, new FutureCallback<List<String>>() {

            @Override
            public void onFailure(final Throwable arg0) {
                System.out.println("> FAILURE");
            }

            @SuppressWarnings("synthetic-access")
            @Override
            public void onSuccess(final List<String> arg0) {
                System.out.println("> SUCCESS");
                // Update the UI on the SWT UI thread
                display.asyncExec(new Runnable() {

                    @Override
                    public void run() {
                        final StringBuilder sb = new StringBuilder();
                        for (final String s : arg0) {
                            sb.append(s + "\n");
                        }
                        final String resultString = sb.toString();
                        output.setText(resultString);
                    }

                });
            }

        });
    }

    public void run() {
        shell.setSize(200, 200);
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        executor.shutdownNow();
        display.dispose();
    }

    public static void main(final String... args) {
        new CallbackExample().run();
    }

}
import java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.Callable;
导入java.util.concurrent.Executors;
导入org.eclipse.swt.swt;
导入org.eclipse.swt.events.SelectionAdapter;
导入org.eclipse.swt.events.SelectionEvent;
导入org.eclipse.swt.layout.FillLayout;
导入org.eclipse.swt.layout.GridData;
导入org.eclipse.swt.layout.GridLayout;
导入org.eclipse.swt.widgets.Button;
导入org.eclipse.swt.widgets.Composite;
导入org.eclipse.swt.widgets.Display;
导入org.eclipse.swt.widgets.Shell;
导入org.eclipse.swt.widgets.Text;
导入com.google.common.util.concurrent.FutureCallback;
导入com.google.common.util.concurrent.Futures;
导入com.google.common.util.concurrent.ListenableFuture;
导入com.google.common.util.concurrent.ListingExecutorService;
导入com.google.common.util.concurrent.MoreExecutors;
公共类回调示例{
私人最终展示;
私有最终外壳;
私人最终文本输出;
私人最终清单执行人服务执行人;
公共回调示例(){
显示=新显示();
外壳=新外壳(显示);
setLayout(新的FillLayout());
executor=更多Executors.ListingDecorator(Executors
.newFixedThreadPool(20));
最终复合材料基础复合材料=新复合材料(壳体,SWT.无);
基复合材料
.setLayoutData(新网格数据(SWT.FILL,SWT.FILL,true,true));
setLayout(新的GridLayout());
输出=新文本(baseComposite,SWT.MULTI | SWT.BORDER | SWT.V|滚动);
setLayoutData(新的GridData(SWT.FILL,SWT.FILL,true,true));
最终按钮=新按钮(基本组合,SWT.PUSH);
setLayoutData(新的GridData(SWT.FILL,SWT.FILL,true,false));
setText(“启动任务”);
addSelectionListener(新建SelectionAdapter(){
@抑制警告(“合成访问”)
@凌驾
公共无效WidgeSelected(最终选择事件e){
//单击按钮时启动任务
startTasks();
}
});
}
私有无效startTasks(){
//创建一个列表以保存任务的ListenableFutures
最终列表期货=新的ArrayList();
//提交所有要执行的任务(在本例中为100)
对于(int i=0;i<100;i++){
最终可上市未来=执行人
.submit(新的可调用(){
@凌驾
公共字符串调用()引发异常{
//完成这项工作!这里我们睡觉来模拟一项长任务
Display.getCurrent().asyncExec(new Runnable() {
    @Override
    public void run() {
        // Update the UI
    }
});
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

public class CallbackExample {

    private final Display display;
    private final Shell shell;
    private final Text output;
    private final ListeningExecutorService executor;

    public CallbackExample() {
        display = new Display();
        shell = new Shell(display);
        shell.setLayout(new FillLayout());

        executor = MoreExecutors.listeningDecorator(Executors
                .newFixedThreadPool(20));

        final Composite baseComposite = new Composite(shell, SWT.NONE);
        baseComposite
                .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        baseComposite.setLayout(new GridLayout());

        output = new Text(baseComposite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
        output.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        final Button button = new Button(baseComposite, SWT.PUSH);
        button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        button.setText("Start tasks");
        button.addSelectionListener(new SelectionAdapter() {

            @SuppressWarnings("synthetic-access")
            @Override
            public void widgetSelected(final SelectionEvent e) {
                // Start tasks when the button is clicked
                startTasks();
            }

        });

    }

    private void startTasks() {
        // Create a List to hold the ListenableFutures for the tasks
        final List<ListenableFuture<String>> futures = new ArrayList<ListenableFuture<String>>();
        // Submit all the tasks for execution (in this case 100)
        for (int i = 0; i < 100; i++) {
            final ListenableFuture<String> future = executor
                    .submit(new Callable<String>() {
                        @Override
                        public String call() throws Exception {
                            // Do the work! Here we sleep to simulate a long task
                            Thread.sleep(2000);
                            final long currentMillis = System
                                    .currentTimeMillis();
                            System.out.println("Task complete at "
                                    + currentMillis);
                            return "Task complete at " + currentMillis;
                        }
                    });
            // Add the future for this task to the list
            futures.add(future);
        }
        // Combine all of the futures into a single one that we can wait on
        final ListenableFuture<List<String>> future = Futures
                .allAsList(futures);
        // Add the callback for execution upon completion of ALL tasks
        Futures.addCallback(future, new FutureCallback<List<String>>() {

            @Override
            public void onFailure(final Throwable arg0) {
                System.out.println("> FAILURE");
            }

            @SuppressWarnings("synthetic-access")
            @Override
            public void onSuccess(final List<String> arg0) {
                System.out.println("> SUCCESS");
                // Update the UI on the SWT UI thread
                display.asyncExec(new Runnable() {

                    @Override
                    public void run() {
                        final StringBuilder sb = new StringBuilder();
                        for (final String s : arg0) {
                            sb.append(s + "\n");
                        }
                        final String resultString = sb.toString();
                        output.setText(resultString);
                    }

                });
            }

        });
    }

    public void run() {
        shell.setSize(200, 200);
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        executor.shutdownNow();
        display.dispose();
    }

    public static void main(final String... args) {
        new CallbackExample().run();
    }

}