跟中学语文课本上面描述的统筹方法一样, 当存在多个任务: 煮饭, 洗衣两个任务发生时, 如何异步的处理所有事情, 节省时间。
非统筹是这样做的【同步方法】:
第一步: 洗米, 煮饭,打开电饭煲
第二步:等待, 直到饭煮好后, 再洗衣服
统筹是这样做的【异步方法】:
第一步: 洗米, 煮饭,打开电饭煲
第二步:不理会煮饭, 直接洗衣服
举例以下几种耗时操作:
1. 界面调用一个耗时的后台操作(以SWT 为例)
2. Java 调用一个耗时的本地代码(JNI)
耗时操作危害是很大的, 比如界面如果调用耗时的后台操作, 整个界面都会假死, 用户误认为软件出现死机, JNI中, JVM调用本地代码直到本地代码返回, 非常容易出现假挂死的问题。
本章就是要讲解异步安排耗时任务, 提高解决问题效率的方法。
界面调用耗时操作的例子:
当GUI调用一个复杂的后台操作时, 如果按照普通方式组织代码, 则GUI会阻塞,知道后台操作完成. 这样GUI会完全假死——点击和拖动界面, 将没有任何响应。直到后台处理完毕。
解决方法:
1. 将耗时操作作为独立的线程启动.
2. 独立后台线程中, 一方面调用后台事物处理, 另一方面, 处理完毕后, 更新GUI线程
package com.huawei.galaxy.timeConsuming; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class TimeConsuming { private static Button btn; /** * Launch the application * @param args */ public static void main(String[] args) { final Display display = Display.getDefault(); final Shell shell = new Shell(); shell.setSize(500, 375); shell.setText("SWT Application"); shell.setLayout(new FillLayout()); btn = new Button(shell, SWT.NULL); btn.setText("shit"); registerAction(); shell.open(); shell.layout(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } shell.dispose(); display.dispose(); } private static void processTimeConsumingAction() { //启动线程目的是保证可以返回 Thread t = new Thread(new Runnable(){ @Override public void run() { final String s = getResultInTimeConsumeFunction(); final Display display = Display.getDefault(); if ((display != null) && (!display.isDisposed())) { display.asyncExec(new Runnable(){ @Override public void run() { updateGUI(s); }}); } }}); t.start(); } private static String getResultInTimeConsumeFunction() { try { //处理一个耗时巨大的工作, 处理完之后, 此过程中, 更新界面显示 Thread.sleep(5000); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } return "改变呀改变"; } private static void updateGUI(String s) { btn.setText(s); } private static void registerAction() { btn.addMouseListener(new MouseListener(){ @Override public void mouseDoubleClick(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseDown(MouseEvent e) { processTimeConsumingAction(); } @Override public void mouseUp(MouseEvent e) { }}); } }