一、定义产生返回值的任务

在上一篇文的介绍中,我们知道了定义任务通常的方法是定义一个实现Runnable接口的类,这个类被我们成为任务。然而也很容易注意到,任务的最重要的一个方法就是run( )方法,而run( )方法是没有返回值的,也就是说我们之前定义的任务不返回任何值。

如果想要定义一个有返回值的任务,则需要编写一个实现Callable接口的类。Callable是一种具有类型参数的泛型,他的类型参数表示的是call( )方法的返回值类型。

示例如下:

 import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; /**
* @author Gao
* Date:2016.5
* */ class Task implements Callable<String> {
int testNum;
public Task(int testNum) {
this.testNum = testNum;
}
public String call() {
return "Test number is " + testNum;
}
} public class ReturnedDemo {
public static void main(String[] args) {
//创建ExecutorService的实例化对象,用来执行任务。
ExecutorService exec = Executors.newCachedThreadPool();
Future<String> future = exec.submit(new Task(123));
try { System.out.println(future.get());
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (ExecutionException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} }
}
/*Output:
Test number is 123
*/

在上面的示例代码中你可能会不了解Future<T>的含义。ExecutorService类的实例化对象在调用submit( )方法时会返回Future<T>类型的返回值,我们在这里实例化的future对象用来保存该返回值,在之后用来处理和其他过程。同时,在调用get( )方法时会产生异常,所以该段用try-catch块进行包围。

二、线程的优先级与让步

1.线程的优先级

线程由线程调度器调用执行,线程调度器进行线程调度的时候倾向于让优先级高的线程先运行。但是由于CPU处理线程集的顺序是不固定的,因此线程调度器只是起到一个“建议”的作用,而不是决定性作用。同时,线程优先级只是代表线程集中的线程执行的频率。高优先级的线程执行的频率较高,但是低优先级的线程也会得到执行。

由于不同操作系统的优先级不同且和JDK的优先级不同(JDK有10个优先级),所以JDK和操作系统优先级的映射不是很好。通常我们在调整优先级的时候,仅仅使用MAX_PRIORITY、NORM_PRIORITY、MIN_PRIORITY三种级别。

示例代码如下:

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* @author Gao
* Date:2016.5
* */
class PriorityTask implements Runnable {
int priority;
public PriorityTask(int priority) {
this.priority = priority;
}
@Override
public void run() {
Thread.currentThread().setPriority(priority);
System.out.println(this);
}
public String toString() {
return Thread.currentThread() + ";";
}
}
public class PriorityTest {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(new PriorityTask(Thread.MAX_PRIORITY));
exec.execute(new PriorityTask(Thread.MIN_PRIORITY));
exec.shutdown(); }
}
/*Output:
Thread[pool-1-thread-3,10,main];
Thread[pool-1-thread-4,10,main];
Thread[pool-1-thread-1,10,main];
Thread[pool-1-thread-5,10,main];
Thread[pool-1-thread-2,10,main];
Thread[pool-1-thread-6,1,main]; */

在该示例中,我们通过给线程设置不同的优先级来定义线程,在线程的信息中会显示其优先级。

2.线程的让步

在第一篇文章的介绍中,我们在例子中应用了Thread.yield( )这一方法,这个方法表现的就是线程的让步。通常我们在run( )方法的其他方法体执行完成之后执行这一方法,意在给线程调度器发送一个信号,告诉线程调度器自己的工作已经基本执行完毕,可以将CPU分配给其他线程进行使用了。但是和上面的线程优先级中的介绍一样,由于CPU处理现有线程集的顺序是不确定的,所以yield( )方法只是给调度器一个建议,并不是真正的在执行yield( )方法后就将CPU分给其他同级别需要CPU的线程。

3.后台线程

(1)后台线程的定义:后台线程是指在程序运行的时候在后台提供一种通用服务的线程,

这种线程一般不属于程序不可缺少的部分。

(2)后台线程的设置:利用线程对象调用setDaemon( )方法,可将其设置为后台线程。

注:必须在线程启动之前设置,才能成功将其设置为后台线程。

三、与线程有关的异常问题

提起异常,想必大家都不会感到陌生。对于多线程编程中来说,如果你不采用一些步骤来捕获这些异常,则一旦异常逃出任务的run( )方法,它就会向外传播到控制台。

目前为了解决线程异常捕获的问题,我们可以通过修改Executor产生线程的方式。实现的基础是Java提供的接口:Thread.UncaughtExceptionHandler。该接口允许程序员在编写的每个Thread对象上都附着一个异常处理器。

ps:有关于异常的例子会在下一篇博文中介绍并解释。

Java多线程学习(二)的更多相关文章

  1. Java多线程学习(二)---线程创建方式

    线程创建方式 摘要: 1. 通过继承Thread类来创建并启动多线程的方式 2. 通过实现Runnable接口来创建并启动线程的方式 3. 通过实现Callable接口来创建并启动线程的方式 4. 总 ...

  2. java多线程学习二

    声明:本篇博客是本人为了自己学习保存的心得,其内容主要是从大神——五月的仓颉的博客中学习而来,在此多谢大神五月的仓颉的分享,敬礼!如有疑问请联系博主,谢谢! 本章主要记录并讲述线程在项目中常用的方法: ...

  3. Java多线程学习(二)synchronized关键字(2)

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79670775 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

  4. Java多线程学习(二)synchronized关键字(1)

    转载请备注地址: https://blog.csdn.net/qq_34337272/article/details/79655194 Java多线程学习(二)将分为两篇文章介绍synchronize ...

  5. Java多线程学习笔记

    进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ...

  6. Java多线程学习(转载)

    Java多线程学习(转载) 时间:2015-03-14 13:53:14      阅读:137413      评论:4      收藏:3      [点我收藏+] 转载 :http://blog ...

  7. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

  8. JAVA多线程学习笔记(1)

    JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...

  9. Java多线程学习(六)Lock锁的使用

    系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...

  10. Java多线程学习(五)线程间通信知识点补充

    系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...

随机推荐

  1. ZeroMQ接口函数之 :zmq_ctx_new – 创建一个新的ZMQ 环境上下文

    ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_ctx_new zmq_ctx_new(3)               ØMQ Manual - ØMQ/3.2 ...

  2. sqlserver2008 函数1

    SQL2008 表达式:是常量.变量.列或函数等与运算符的任意组合. 1. 字符串函数 函数 名称 参数 示例 说明 ascii(字符串表达式) select ascii('abc') 返回 97 返 ...

  3. seajs实现JavaScript 的 模块开发及按模块加载

    seajs实现了JavaScript 的 模块开发及按模块加载.用来解决繁琐的js命名冲突,文件依赖等问题,其主要目的是令JavaScript开发模块化并可以轻松愉悦进行加载. 官方文档:http:/ ...

  4. c++聪聪看书(低数据版代码)

    聪聪是一个善良可爱.睿智聪慧的好孩子.聪聪喜欢看书,这一天她在看一本书时看到了这样一个问题:给你一个正整数n,你要将它分成若干个自然数Ai的和的形式,并且使得这若干个自然数Ai的乘积尽量大,并输出最大 ...

  5. Servlet异步上传文件

    这里需要用到插件ajaxfileupload.js,jar包:commons-fileupload-1.3.2.jar,commons-io-2.5.jar 注意红色部分的字!!!! 1.创建一个we ...

  6. Windows下用VMware安装Ubuntu虚拟机

    安装: http://jingyan.baidu.com/article/0320e2c1ef9f6c1b87507bf6.html 全屏: http://jingyan.baidu.com/arti ...

  7. 关于Unity3D手机网游开发一些小看法

    它的知识技能和职责,我就不仔细说了,说细了有一点像招聘启示.他的主要职责虽然负责技术,但是也给产品决策和方向提供一些决策.他最主要的考核指标,就是经验很重要,最好主导或参与过一款网络游戏的开发.举个例 ...

  8. jquery的$().each,$.each的区别

    在jquery中,遍历对象和数组,经常会用到$().each和$.each(),两个方法.两个方法是有区别的,从而这两个方法在针对不同的操作上,显示了各自的特点. $().each,对于这个方法,在d ...

  9. id to load is required for loading

    id一般作为主键,不为空.springmvc hibernate 框架中根据参数ids执行批量删除的方法时报错,ids是id主键的数组集合.去搜了下,原因别的博客说了,是id为空引起的.实际上id不为 ...

  10. Jmeter学习(三十三)调试工具Debug Sampler

    一.Debug Sampler介绍: 使用Jmeter开发脚本时,难免需要调试,这时可以使用Jmeter的Debug Sampler,它有三个选项:JMeter properties,JMeter v ...