Callable在多线程合理优化使用

Future对象在执行使用在外线程中还是同步执行
public class CallableFutureTest {
ExecutorService executor = Executors.newFixedThreadPool(3);

@Test
//@Ignore
public void testCallable() {
long start=System.currentTimeMillis();
try {
for (int i = 0; i < 5; i++) {
Callable c = new Callable() {
public Object call() throws Exception {
Boolean random = new Random().nextBoolean();
System.out.println(Thread.currentThread().getName() + "任务启动" + random);
Thread.sleep(3000);
return random;
}
};
Future<Boolean> f = executor.submit(c);
if (!f.get()) {
System.out.println("执行continue操作" + f.get());
continue;
}
System.out.println("执行后插入数据");
}
System.out.println("执行时间最后用时-------------------------"+(System.currentTimeMillis()-start));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
}
}

执行后的结果用时
Connected to the target VM, address: '127.0.0.1:50960', transport: 'socket'
pool-1-thread-1任务启动true
执行后插入数据
pool-1-thread-2任务启动false
执行continue操作false
pool-1-thread-3任务启动true
执行后插入数据
pool-1-thread-1任务启动false
执行continue操作false
pool-1-thread-2任务启动false
执行continue操作false
执行时间最后用时-------------------------14979

[b]看到前面的调用使用了future并没有体现出他的优势,所以在使用时候调用还是同步,我改进一下调用优化[/b]
public class CallableFutureTest {
ExecutorService executor = Executors.newFixedThreadPool(3);

@Test
public void testCallable() {
long start=System.currentTimeMillis();
//创建多个线程的返回值
List<Future> list = Lists.newArrayList();
try {
for (int i = 0; i < 5; i++) {
Callable c = new Callable() {
public Object call() throws Exception {
Boolean random = new Random().nextBoolean();
System.out.println(Thread.currentThread().getName() + "任务启动" + random);
Thread.sleep(3000);
return random;
}
};
Future<Boolean> f = executor.submit(c);
list.add(f);
}
for (Future<Boolean> future : list) {
if (!future.get()) {
System.out.println("执行continue操作" + future.get());
continue;
}
System.out.println("执行后插入数据");
}
System.out.println("执行时间最后用时-------------------------"+(System.currentTimeMillis()-start));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();

}
}

改进后执行后的用时
Connected to the target VM, address: '127.0.0.1:52304', transport: 'socket'
pool-1-thread-1任务启动true
pool-1-thread-2任务启动true
pool-1-thread-3任务启动true
pool-1-thread-3任务启动true
执行后插入数据
执行后插入数据
执行后插入数据
pool-1-thread-2任务启动false
Disconnected from the target VM, address: '127.0.0.1:52304', transport: 'socket'
执行后插入数据
执行continue操作false
执行时间最后用时-------------------------6018


如果在调用时候发生异常情况会怎么样,上边的如果有异常发生会出现消息不能正常处理。看看结果
@Test
public void testCallable() {
long start = System.currentTimeMillis();
//创建多个线程的返回值
List<Future> list = Lists.newArrayList();

for (int i = 0; i < 5; i++) {

Callable c = new Callable() {
public Object call() throws Exception {
Boolean random = new Random().nextBoolean();
System.out.println(Thread.currentThread().getName() + "任务启动" + random);
Thread.sleep(2000);
if (!random) {
throw new InterruptedException("执行线程被打断异常");
}
return random;
}
};
Future<Boolean> f = executor.submit(c);
list.add(f);
}
try {
for (Future<Boolean> future : list) {

if (!future.get()) {
System.out.println("执行continue操作" + future.get());
continue;
}
System.out.println("执行后插入数据");

} } catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("执行时间最后用时-------------------------" + (System.currentTimeMillis() - start));

executor.shutdown();

}

抛出异常后的执行结果可以看到只要前面有异常就会阻碍后边的程序执行
pool-1-thread-1任务启动false
pool-1-thread-2任务启动false
pool-1-thread-3任务启动false
pool-1-thread-2任务启动false
pool-1-thread-3任务启动true
执行时间最后用时-------------------------2015
java.util.concurrent.ExecutionException: java.lang.InterruptedException: 执行线程被打断异常
Caused by: java.lang.InterruptedException: 执行线程被打断异常

继续优化异常捕获
@Test
public void testCallable() {
long start = System.currentTimeMillis();
//创建多个线程的返回值
List<Future> list = Lists.newArrayList();

for (int i = 0; i < 5; i++) {

Callable c = new Callable() {
public Object call() throws Exception {
Boolean random = new Random().nextBoolean();
System.out.println(Thread.currentThread().getName() + "任务启动" + random);
Thread.sleep(2000);
if (!random) {
throw new InterruptedException("执行线程被打断异常");
}
return random;
}
};
Future<Boolean> f = executor.submit(c);
list.add(f);
}
for (Future<Boolean> future : list) {
try {
if (!future.get()) {
System.out.println("执行continue操作" + future.get());
continue;
}
System.out.println("执行后插入数据");
} catch (InterruptedException e) {
System.out.println("-----------------------------执行中途有异常出现InterruptedException");
e.printStackTrace();
} catch (ExecutionException e) {
System.out.println("-----------------------------执行中途有异常出现ExecutionException");
e.printStackTrace();
}
}
System.out.println("执行时间最后用时-------------------------" + (System.currentTimeMillis() - start));

executor.shutdown();

}

看看执行后的日志记录

pool-1-thread-1任务启动false
pool-1-thread-2任务启动true
pool-1-thread-3任务启动true
pool-1-thread-3任务启动true
pool-1-thread-2任务启动false
-----------------------------执行中途有异常出现ExecutionException
执行后插入数据
执行后插入数据
java.util.concurrent.ExecutionException: java.lang.InterruptedException: 执行线程被打断异常
Caused by: java.lang.InterruptedException: 执行线程被打断异常
执行后插入数据
java.util.concurrent.ExecutionException: java.lang.InterruptedException: 执行线程被打断异常
Caused by: java.lang.InterruptedException: 执行线程被打断异常
Disconnected from the target VM, address: '127.0.0.1:55843', transport: 'socket'
-----------------------------执行中途有异常出现ExecutionException
执行时间最后用时-------------------------4028

可以看见执行成功执行的会正常执行完成,想象一下这里我们可以自己处理这些异常,比如将没有执行成功的数据放入消息队列或者放入数据库都可以,等待下次处理或找到调用的问题。

[b]最后版本[/b]
@Test
public void testCallable() {
long start = System.currentTimeMillis();
//创建多个线程的返回值
List<Future> list = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
Callable c = new Callable() {
public Object call() throws Exception {
Boolean random = new Random().nextBoolean();
System.out.println(Thread.currentThread().getName() + "任务启动" + random);
Thread.sleep(2000);
if (!random) {
throw new InterruptedException("执行线程被打断异常");
}
return random;
}
};
Future<Boolean> f = executor.submit(c);
list.add(f);
}
for (Future<Boolean> future : list) {
try {
if (!future.get()) {
System.out.println("执行continue操作" + future.get());
continue;
}
System.out.println("执行后插入数据成功");
} catch (InterruptedException e) {
System.out.println("将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现InterruptedException");
continue;
} catch (ExecutionException e) {
System.out.println("将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现ExecutionException");
continue;
}
}
System.out.println("执行时间最后用时-------------------------" + (System.currentTimeMillis() - start));
executor.shutdown();//记住这里在使用完后一定要关闭避免引起资源的浪费和死锁
}


现在我们看看最后的执行效果,看着就很舒服了
Connected to the target VM, address: '127.0.0.1:56951', transport: 'socket'
pool-1-thread-1任务启动true
pool-1-thread-3任务启动false
pool-1-thread-2任务启动false
执行后插入数据
pool-1-thread-1任务启动false
pool-1-thread-3任务启动true
将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现ExecutionException
将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现ExecutionException
Disconnected from the target VM, address: '127.0.0.1:56951', transport: 'socket'
将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现ExecutionException
执行后插入数据
执行时间最后用时-------------------------4013


实际使用中可能会有不同的callable调用,你可以实现自己的callable。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值