多任务处理是提升系统性能的理想选择,下面给出两种实现方案,分别介绍了ExecutorService结合Callable接口利用线程池提交任务,以及更高效的CompletionService接口实现多任务处理实践。
package thread;
import java.util.concurrent.*;
public class Refresh {
private final ExecutorService executorService = Executors.newCachedThreadPool();
private static int result = 2;
public void bussiness(){
Callable<Integer> task = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i=0; i < 10; i++){
sum += i;
}
Thread.sleep(10000);
return sum;
}
};
long start = System.currentTimeMillis();
Future<Integer> submit = executorService.submit(task);
System.out.println("do other work");
executorService.execute(new LoadClass());
System.out.println("接着干");
try {
this.result = submit.get();
System.out.println("等待了" + (System.currentTimeMillis() - start) / 1000 + "s");
} catch (InterruptedException e) {
Thread.currentThread().isInterrupted();
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
private static class LoadClass implements Runnable{
@Override
public void run() {
while (result == 2){
try {
Thread.sleep(1000);
System.out.println("我在等你不再2了");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
System.out.println("终于不2了");
}
}
public static void main(String[] args) {
new Refresh().bussiness();
}
}
上面这种实现方式虽然能多个任务一起处理,但是因为主线程结果要依赖每一个(所有)任务返回结果(Future),所以会多出时间去等待所有结果,造成没必要的等待,对系统性能造成影响。
下面给出另外一种方式
package thread;
import java.util.concurrent.*;
public class RefreshOther {
private final ExecutorService executorService = Executors.newCachedThreadPool();
private static int result = 0;
public void bussiness(){
CompletionService<Integer> completionService = new ExecutorCompletionService<>(executorService);
int time=0;
for(int i=0; i<10; i++){
int finalK = i;
time+=1000; // 睡眠时间,模拟延迟每一个任务返回结果,体现异步更新结果
int finalTime = time;
completionService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return new LoadClass(finalK, finalTime).print();
}
});
}
System.out.println("do other work start");
Bussiness bussiness = new Bussiness();
bussiness.setInput(0);
LoadClass loadClass = new LoadClass(bussiness);
executorService.execute(loadClass); // 这里依赖上面任务返回的值
for(int i=0; i<10; i++){
try {
Future<Integer> take = completionService.take();
Thread.sleep(3000); // 这里为了确保后面能够拿到每一个任务返回的结果
result = take.get();
bussiness.setInput(result);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class LoadClass implements Runnable{
private long time;
private int i;
private Bussiness tm;
LoadClass(Bussiness temp){
this.tm = temp;
}
LoadClass(int i, long time){
this.time = time;
this.i = i;
}
private int print(){
try {
Thread.sleep(this.time);
} catch (InterruptedException e) {
e.printStackTrace();
}
return this.i;
}
@Override
public void run() {
int now = -1;
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(tm.getInput() != now){
System.out.println("我现在变为:" + tm.getInput());
now = tm.getInput();
}
if(tm.getInput() == 9) // 特殊处理让程序结束
break;
}
System.out.println("-------- the end ---------");
}
}
public static void main(String[] args) {
new RefreshOther().bussiness();
}
}
package thread;
public class Bussiness {
private Integer input;
public Integer getInput() {
return input;
}
public void setInput(Integer input) {
this.input = input;
}
}
程序执行结果如下
上面的方案是利用了CompletionService能实现任务异步处理特性,任务处理和提交同时进行,并且让Future接受每一个任务执行结果。由于任务能够异步处理返回,因此没有产生多余的等待时间,较上一种实现方案,使用CompletionService来实现性能更高、更有效。