首页 > 编程语言 > Java编程思想18

Java编程思想18

时间:2022-12-26 10:56:43浏览次数:44  
标签:Java Thread 18 编程 System TaskWithResult println new public

从任务种产生返回值:Runnable是执行工作的独立任务,但是它不返回任何值。如果你希望在任务完成时能够返回一个值,那么可以实现Callable接口而不是Runnable接口。在Java SE5中引入的Callable是一种具有类型参数的泛型,它的类型参数表示的是从方法call()中返回的值,并且必须使用ExecutorService.submit()方法调用它,下面是一个简单示例:

package concurrency;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
* @author Mr.Sun
* @date 2022年09月03日 16:23
*
* 从任务中产生返回值
*/
public class CallableDemo {

public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
List<Future<String>> futureList = new ArrayList<>();

for (int i = 0; i < 10; i++) {
futureList.add(exec.submit(new TaskWithResult(i)));
}

for (Future<String> result : futureList) {
try {
// get() 会阻塞知道任务完成
System.out.println(result.get());
} catch (InterruptedException e) {
System.out.println(e);
return;
} catch (ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}
}

class TaskWithResult implements Callable<String> {

private int id;

public TaskWithResult(int id) {
this.id = id;
}

@Override
public String call() throws Exception {
return "result of TaskWithResult " + id;
}
} /* Output:
result of TaskWithResult 0
result of TaskWithResult 1
result of TaskWithResult 2
result of TaskWithResult 3
result of TaskWithResult 4
result of TaskWithResult 5
result of TaskWithResult 6
result of TaskWithResult 7
result of TaskWithResult 8
result of TaskWithResult 9
*///:~

 

submit()方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化。你可以用isDone()方法来查询Future是否已经完成。当任务完成时,它具有一个结果,你可以调用get()方法来获取该结果。你也可以不用isDone()进行检查就直接调用get(),在这种情况下,get()将阻塞,直至结果准备就绪。你还可以在试图调用get()来获取结果之前,先调用具有超时的get(),或者调用isDone()来查看任务是否完成。

捕获异常
  由于线程的本质特性,使得你不能捕获从线程中逃逸的异常。下面的任务总是抛出一个异常,该异常会传播到run()方法的外部,并且main()展示了当你运行它时所发生的事情:

package concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* @author Mr.Sun
* @date 2022年09月03日 17:00
*
* 线程抛出异常
*/
public class ExceptionThread implements Runnable {

@Override
public void run() {
throw new RuntimeException();
}

public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExceptionThread());
exec.shutdown();
}
}

 

 将main()的主体放到try-catch子句中是没有作用的,如下:

 

 

我们发现使用try-catch后,异常仍未被捕获。

  为了解决这个问题,我们要修改Executor产生线程的方式。Thread.UncaughtExceptionHandler是Java SE5中的新接口,它允许你在每个Thread对象上都附着一个异常处理器。Thread.UncaughtExceptionHandler.uncaughtException()会在线程因未捕获的异常而临近死亡时被调用。为了使用它,我们创建了一个新类型的ThreadFactory,它将在每个新创建的Thread对象上附着一个Thread.UncaughtExceptionHandler。我们将这个工厂传递给Executors创建新的ExecutorService的方法:

package concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
* @author Mr.Sun
* @date 2022年09月03日 17:10
*
* 为每个Thread对象附着一个异常处理器
*/
public class CaptureUncaughtException {

public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool(new HandlerThreadFactory());
exec.execute(new ExceptionThread2());
}
}

class ExceptionThread2 implements Runnable {

@Override
public void run() {
Thread t = Thread.currentThread();
System.out.println("run() by " + t);
System.out.println("eh = " + t.getUncaughtExceptionHandler());
throw new RuntimeException();
}
}

class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("caught " + e);
}
}

class HandlerThreadFactory implements ThreadFactory {

@Override
public Thread newThread(Runnable r) {
System.out.println(this + " creating new Thread");
Thread t = new Thread(r);
System.out.println("created " + t);
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
System.out.println("eh = " + t.getUncaughtExceptionHandler());
return t;
}
} /* Output:
concurrency.HandlerThreadFactory@1540e19d creating new Thread
created Thread[Thread-0,5,main]
eh = concurrency.MyUncaughtExceptionHandler@677327b6
run() by Thread[Thread-0,5,main]
eh = concurrency.MyUncaughtExceptionHandler@677327b6
caught java.lang.RuntimeException
*///:~

 在程序中添加了额外的跟踪机制,用来验证工厂创建的线程会传递给UncaughtExceptionHandler。你可以看到,未捕获的异常是通过uncaughtException来捕获的。

标签:Java,Thread,18,编程,System,TaskWithResult,println,new,public
From: https://www.cnblogs.com/LvJinshuai/p/17005216.html

相关文章

  • Java编程思想19
    共享受限资源1.不正确访问资源  考虑下面的例子,其中一个任务产生产生偶数,而其他任务消费这些数字。而这些消费者任务的唯一工作就是校验偶数的有效性packageconcurr......
  • 实现JNI的另一种方法:使用RegisterNatives方法传递和使用Java自定义类
    除了使用传统方法实现JNI外,也可以使用RegisterNatives实现JNI。和传统方法相比,使用RegisterNatives的好处有三点:1、C++中函数命名自由,不必像javah自动生成的函数声明那样,拘......
  • 【HMS Core】升级SDK报错app_id failed: java.io.FileNotFoundException: agconnect-s
    问题描述:升级推送服务最新版SDK报错app_idfailed:java.io.FileNotFoundException:agconnect-services.json问题分析:从日志来看,是没有找到agconnect-services.json文件。......
  • Java小白必会!Intellij IDEA安装、配置及使用详细教程
    一.前言所谓工欲善其事必先利其器,一个好的工具对工作效率的提升是有非常大的帮助的。而在咱们程序员开发时,一个好的集成开发工具对于提高我们的编码效率和编程体验来说也是......
  • Java版小米商城项目简介
    小米商城课程详情1.课程介绍本套课程主要是基于Servlet、HTML、JS、Ajax、JSP、MySQL、JDBC、Tomcat、微信支付等web技术,仿照小米商城来实现一个电子商城项目。注意:本课程配......
  • 1:Web开发入门-Java Web
    (目录)1.1什么是Web应用程序在Sun的JavaServlet规范中,对JavaWeb应用作了这样定义:“JavaWeb应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在......
  • java的异常体系图
    本文主要讲述java的异常体系图老韩图解:  自己理解: ......
  • JavaVM & JNIEnv
    JNIEnv提供了大多数的JNI函数。你的本地方法都会接收JNIEnv作为第一个参数。JNIEnv用于本地线程存储。因此,你不能在线程间共享同一个JNIEnv。如果一个代码段没有其他方式获......
  • 【HMS Core】升级SDK报错app_id failed: java.io.FileNotFoundException: agconnect-s
    ​问题描述:升级推送服务最新版SDK报错app_idfailed:java.io.FileNotFoundException:agconnect-services.json 问题分析:从日志来看,是没有找到agconnect-services.js......
  • 第一个Java程序——Hello World
    环境:记事本、DOS窗口步骤:编写代码文件,后缀改为java打开DOS窗口找到代码存放位置使用 javacHelloWorld.java进行编译使用javaHelloWorld 执行代码:1p......