从java线程中获得运算结果(原创) 如果有任何的意见、批评或表扬:),请给我来信[email protected]
java的线程是由Thread来实现的,一般我们创建线程进行一个复杂的运算,然后在主线程中对运算结果进行处理,但是Thread的run函数并没有返回值,那么我们运算出结果后,怎么通知其它线程呢,本文讲述了几种返回信息的方法。
一。java线程的创建
要创建线程有两种办法,一是继承Thread类,二是实现Runnable,然后将其传递给一个Thread的构造函数,实例如下(假设我们要在一个线程中计算1到10000的和):
1。继承Thread: public class AddThread extends Thread { public void run() { int result = 0; for(int i = 1; i <= 10000; i++) { result += i; } } }
运行AddThread: AddThread thread = new AddThread(); thread.start();
2。实现接口Runnable:
public class Add implements Runnable { public void run() { int result = 0; for(int i = 1; i <= 10000; i++) { result += i; } } }
运行该线程: Thread thread = new Thread(new Add()); thread.start();
二、返回运算结果的方法 现在我们启动这个加法线程后,需要从这个线程中得到运算的结果,例如我们要在主线程中对运算结果进行显示。那么我们怎么实现呢?下面就讲述几种常见的方法,注意其中有一些是错误的方法
1。使用get方法(错误的) 我们可以在AddThread中加入一个getResult函数得到运算结果: public class AddThread extends Thread { private int result = 0; public void run() { for(int i = 0; i <= 10000; i++) result += i; } public int getResult() { return result; } } /** 得到运算结果并显示在屏幕上 */ public class Test { public static void main(String[] args) { AddThread thread = new AddThread(); thread.start(); System.out.println("result is " + thread.getResult()); } } 得到的结果是: result is 0 因为这里主线程和addThread线程是同时运行,AddThread的运算还没有完成(甚至可能还没有开始),主线程就开始输出运算结果了,所以这种方式是错误的。 2。查询法(可行,但效率极低) 第二种方法是使用一个变量hasDone来表示运算是否完成,如果hasDone为false的时候表示运算尚未完成,否则表示运算已经完成。主线程不断查询这个变量,如果发现运算尚未完成,则进入循环等待,否则输出运算结果。 public class AddThread extends Thread { private int result = 0; private boolean hasDone = false; public void run() { for(int i = 0; i <= 10000; i++) result += i; hasDone = true; } public boolean hasDone() { return hasDone; } public int getResult() { return result; } } public class Test { public static void main(String[] args) { AddThread thread = new AddThread(); thread.start(); //如果运算没有完成,则循环等待 while (!thread.hasDone()) { try { Thread.sleep(100); } catch (InterruptedException ex) { } } if (thread.hasDone()) System.out.println("result is " + thread.getResult()); } } 结果显示: result is 50005000 主线程中循环查询运算的状态,如果运算没有完成,则主线程sleep100毫秒,然后继续查询,这种方式虽然可行,但由于主线程循环查询,消耗了大量的CPU时间,因此效率很低。 3。wait/notify方式(较好) 第三种方法使用wait/notify的形式,当运算没有结束的时候,主线程进入睡眠状态,这时它不占用CPU,因此效率较高。 public class AddThread extends Thread { //在这个object上wait private Object lock; private int result = 0; private boolean hasDone = false; public AddThread(Object lock) { this.lock = lock; } public void run() { for (int i = 0; i <= 10000; i++) result += i; //运算结束,通知等待的线程 synchronized(lock) { hasDone = true; lock.notifyAll(); } } public boolean hasDone() { return hasDone; } public int getResult() { return result; } } //主线程 public class Test { public static void main(String[] args) { Object lock = new Object(); AddThread thread = new AddThread(lock); thread.start(); synchronized(lock) { while (!thread.hasDone()) { try { //当运算没有结束,主线程进入睡眠状态,当addThread执行notifyAll时,会唤醒主线程 lock.wait(); } catch (InterruptedException ex) { } } } if (thread.hasDone()) System.out.println("result is " + thread.getResult());
}
} 4。使用callback(较好) 我觉得这是最好的一种方式,当运算完成后,AddThread自动调用结果处理类。将其扩展可以成为使多个listener对结果进行处理,这里用到了Observer模式,这种方法很简单,不需要考虑同步机制,具体实现如下: //对结果进行处理的接口 public interface ResultProcessor { public void process(int result); } public class AddThread extends Thread { private ResultProcessor processor; public AddThread(ResultProcessor processor) { this.processor = processor; } public void run() { int result = 0; for(int i = 0; i <= 10000; i++) { result += i; } //对结果进行处理 processor.process(result); } }
public class Test implements ResultProcessor { public void process(int result) { System.out.println("result is " + result); } public static void main(String[] args) { Test test = new Test(); AddThread thread = new AddThread(test); thread.start(); } } 结果显示: result is 50005000 代码如上面,AddThread的构造函数传进一个结果处理类,当运算完成时,自动调用这个类的处理函数对结果进行处理。比较起来,我觉得这种方法最好。 参考文献: 《java newwork programming》 Oreilly 
|