创建线程

Java 中有以下三种方式创建线程,其中前两种无法获取返回值,而最后一种可以获取返回值。

  • 实现 Runnable 接口
  • 继承 Thread 类
  • 通过 Callable、Future 接口配合

实现 Runnable 接口

可以声明一个类实现 Runnable 接口,接着在重写的 run() 方法中编写线程中执行的代码。

class RunnableThread implements Runnable {
@Override
public void run() {
// ...
}
}

接着实例化该类,并作为 Thread 类的构造器参数传入。

Thread runnableThread = new Thread(new RunnableThread());

继承 Thread 类

与实现 Runnable 接口相同,继承也需要重写 run() 方法。

class ExtendThread extends Thread {
@Override
public void run() {
// ...
}
}

不过这种方式创建线程,直接实例化类就可以了。

Thread extendThread = new ExtendThread();

通过 Callable、Future 接口配合

先声明一个类继承 Callable 接口,其中接口中的泛型为返回值的类型,线程中的执行代码在重写的 call() 方法中。

public class ReturnThread implements Callable<String> {
@Override
public String call() {
// ...
return "return value";
}
}

实例化该类,将其提交到线程池(线程池篇会提及)中运行,然后可以通过 get() 方法来获取返回值。

Callable<String> returnThread = new ReturnThread();
Future<String> returnValue = executor.submit(returnThread);
returnValue.get();

FutureTask 类

当通过 submit() 方法向线程池提交任务时,当前线程会阻塞直到返回结果,为了满足不阻塞的需求就有了 FutureTask 类。将上面继承 Callable 接口的类用 FutureTask 类包装后,在提交至线程池中运行。

由于 FutureTask 类实现了 RunnableFuture 接口,而 RunnableFuture 接口继承了 Runnable 和 Future 接口,所以也可以用 get() 方法来获取返回值。

FutureTask<String> futureTask = new FutureTask<>(returnThread);
executor.submit(futureTask);
// Unblock, so can do something here
futureTask.get();

线程的状态及转换

Java 线程有以下七种状态,但除去创建状态和终止状态,就只有和操作系统课程中进程一样的三类状态,分别是就绪、运行和阻塞。

  • 创建状态(new),线程创建完毕
  • 就绪状态(runnable),线程所需资源准备完毕
  • 运行状态(running),线程获得处理机时间
  • 终止状态(dead),线程执行完毕或异常中断
  • 阻塞状态(blocked),线程被同步阻塞或者 IO 阻塞
  • 超时等待(time waiting),线程主动睡眠指定时间
  • 等待阻塞(waiting),线程主动等待

上文创建线程例子中(除开线程池提交例子),当用 new 关键字创建好线程后,线程就进入了创建状态,可以用 start() 方法让线程进入就绪状态(前提是线程所需资源准备完毕),接着就可以等待的调度进入运行状态,然后线程运行完之后进入终止状态。

当线程遇到同步或者 IO 时就会进入阻塞状态,调用 join() 方法可以让线程主动等待另一线程线程执行完毕,而线程中调用 sleep() 方法就可以让线程主动睡眠指定的一段时间,以下为线程状态转换状态图。

new --> runnable <---> running --> dead
| ^
| |
*---> blocked ---*
| |
| |
*---> waiting ---*
| |
| |
*-> time waiting *

Thread 类常用方法

下面列出了 Thread 类中常用的方法。

// 让线程进入就绪状态
start() // 线程主动睡眠指定时间
sleep(long millis)
sleep(long millis, int nanoseconds) // 线程让出处理机时间,给同优先级的线程
// 注意该方法让线程重回就绪状态,而不是阻塞状态
yield() // 等待线程执行完毕,或者等待指定时间
join()
join(long millis)
join(long millis, int nanoseconds) // 中断处于阻塞状态的线程,注意不能中断正在运行中的线程
interrupt() // 获取线程标识符
getID() // 获取设置线程名称
getName()
setName() // 获取设置线程优先级
getPriority()
setPriority() // 设置线程是否为守护线程
setDaemon()
// 判断是否为守护线程
isDaemon()

Java 范例 - 线程的更多相关文章

  1. java基础—线程(一)

    一.线程的基本概念

  2. java之线程

    java之线程 一:线程: 线程是什么呢?线程,有时被称为轻量级进程是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成.另外,线程是进程中的一个实体,是被系统 ...

  3. Java 使用线程方式Thread和Runnable,以及Thread与Runnable的区别

    一. java中实现线程的方式有Thread和Runnable Thread: public class Thread1 extends Thread{ @Override public void r ...

  4. Java的线程安全

    线程安全 我们这里讨论的线程安全,就限定于多个线程之间存在共享数据访问这个前提,因为如果一段代码根本不会与其他线程共享数据,那么从线程安全的角度来看,程序是串行执行还是多线程执行对它来说是完全没有区别 ...

  5. 深入理解Java之线程池

    原作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  6. java中线程分两种,守护线程和用户线程。

    java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...

  7. java 多线程—— 线程让步

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  8. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  9. Java的线程模型

    并发不一定要依赖多线程(如PHP中很常见的多进程并发),但是在Java里面谈论并发,大多数都与线程脱不开关系. 线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开, ...

随机推荐

  1. (转)ASP.NET MVC3 Razor视图引擎-基础语法

    转自:http://kb.cnblogs.com/page/96883/ I:ASP.NET MVC3在Visual Studio 2010中的变化 在VS2010中新建一个MVC3项目可以看出与以往 ...

  2. (转)MVC语法-基础

    好久没有关注微软的开发了,今天看到了MVC3,顺便学习学习,我觉得Razor是个不错的做法,比使用<%%>简单多了,而且好看.首先“_”开头的cshtml文档将不能在服务器上访问,和asp ...

  3. nodejs 负载均衡

    教程:http://taobaofed.org/blog/2015/11/03/nodejs-cluster/ 纠正:net.createServerHandle(); 记录:http://www.j ...

  4. 《javascript高级程序设计》 touch事件的一个小错误

    最近一段时候都在拜读尼古拉斯大神的<javascript高级程序设计>,真的是一本好书,通俗易懂,条理比<javascript权威指南>好理解一些,当然<javascri ...

  5. iOS AppIcon尺寸

    如果提交的ipa包中,未包含必要的Icon就会收到类似的通知,为什么偏偏是Icon-76呢? 因为我们开发的游戏,默认是支持iphone以及ipad的,根据官方提供的参考 Icon-76.png是必须 ...

  6. 一些LinuxC的小知识点(二)

    一.read系统调用       系统调用read的作用是:从与文件描述符filedes相关联的文件里读入nbytes个字节的数据,并把它们放到数据区buf中.它返回实际读入的字节数.这可能会小于请求 ...

  7. C# 使用Google Protocol Buffers

    Google Protocol Buffers 使用3.0版本 下载protoc.exe 下载链接 https://github.com/protocolbuffers/protobuf/releas ...

  8. Spring AOP 源码分析系列文章导读

    1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...

  9. Flask系列05--Flask的配置config

    一.flask配置 示例说明, 就是使用config进行配置 from flask import Flask ​ app = Flask(__name__) # type:Flask app.conf ...

  10. pyqt5 Button.click 报错:argument 1 has unexpected type 'NoneType'

    如上所示,在括号中,添加‘lambda:’,就可以成功运行,不知道为啥. 参考:https://blog.csdn.net/flhsxyz/article/details/79220936?utm_s ...