在java的一个方法里能否并行调用另外类的一个方法

地瓜干 发布于 2011/06/15 17:25
阅读 2K+
收藏 1

如下方法:

public String fun1(HttpServletRequest request){

    BusiBo bo=.....;//这类得到业务BO实例

    String s1=bo.saveData("1111");

    String s2= bo.saveData("2222");

     return s1+s2;

}

比如 bo.saveData方法执行较慢,5秒左右,按上面的顺序方法执行,先执行完 bo.saveData("1111"); 才能执行  bo.saveData("2222");  ,需要10秒左右才能执行完  fun1

能否有方法让   bo.saveData("1111");和  bo.saveData("2222");    并行执行,就是不等  bo.saveData("1111")执行完就开始执行  bo.saveData("222")    ,两个都返回后在往下执行   return s1+s2; ,如果能这样5秒就可以执行完    fun1方法

请各位大侠赐教。 

加载中
1
魏涛
魏涛

献丑了,建议用spring的实现方式,假如项目中有用spring,则修改最少。

项目中没有spring的话,还是用API中的Callable吧。

二者原理都是一样的。

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.commons.lang.math.RandomUtils;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;

public class ThreadApp {
	// @Async注解的方法返回值只能是void或者Future类型。
	@Async
	public Future<Long> saveData(String name) {
		//TODO:具体业务
		long id = Thread.currentThread().getId();
		System.out.println(id + ":" + getClass());
		return new AsyncResult<Long>(id);
	}

	static class FooCallBack implements Callable<Long> {

		private Long id = 0l;

		public FooCallBack(Long id) {
			this.id = id;
		}

		public Long call() throws Exception {
			this.id += 50;
			//TODO:具体业务
			return this.id;
		}

	}

	public static void main(String[] args) throws Exception {

		{
			// spring
			// applicationContext.xml文件中只需要<task:annotation-driven/>
			ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
					"applicationContext.xml");
			ThreadApp app = applicationContext.getBean(ThreadApp.class);
			long m = app.saveData("111").get();
			long n = app.saveData("222").get();
			System.out.println(m + n);
		}
		{
			// api
			ExecutorService executorService = Executors.newFixedThreadPool(10);

			Map<Integer, Future<Long>> map = new HashMap<Integer, Future<Long>>();

			for (int index = 0; index < 100; index++) {
				Long input = RandomUtils.nextLong();
				map.put(index, executorService.submit(new FooCallBack(input)));
			}

			Long result = 0l;
			for (Future<Long> future : map.values()) {
				result += future.get();
			}
			System.out.println(result);
			executorService.shutdown();
		}

	}

}

1
lxbzmy
lxbzmy
我觉得楼主的设计层面有些不妥,既然要并行处理,那么会不会存在锁的问题?或者事务一致性问题。?
0
红薯
红薯
并行? 除非 saveData 里面启动一个线程去执行任务,这样只需要启动线程就可以立即返回,二者就等于并行运行。
0
地瓜干
地瓜干
saveData 里面启动一个线程去执行任务,这样就得不到返回值啊
0
SeekerLee
SeekerLee
java 顺序执行的
0
张亦俊
张亦俊
新建一个线程,然后把返回值用Field记下来,在创建线程把所有创建的线程join,应该可以吧
0
地瓜干
地瓜干

引用来自“张亦俊”的答案

新建一个线程,然后把返回值用Field记下来,在创建线程把所有创建的线程join,应该可以吧
我这个是处理前台的请求,要拿到返回值后返回到前台页面显示
0
CoserSeu
CoserSeu

将几个string:s1,s2封装起来作为一个共享的对象参数传入saveData中,saveData方法中新建一个线程并start(),修改传入的对象的string值,saveData的返回值可以变成子线程对象;在你的fun1方法return前调用jion(),使所有子线程运行完毕;

0
张亦俊
张亦俊

写成这样不行吗?

class Saver extends Thread {

    public Saver(BusiBo bo,String arg) {

        this.bo = bo;

        this.arg = arg;

    }

    private BusiBo bo;

    public String result;//public为了省空间

    private String arg;

    public void run() {

        result = bo.saveData(arg);

    }

}

public String fun1(HttpServletRequest request) {

    //...

    Saver s1 = new Saver(bo,"1111");

    Saver s2 = new Saver(bo,"2222");

    s1.start();

    s2.start();

    s1.join();

    s2.join();

    return s1.result + s2.result;

}


返回顶部
顶部