【Java】多线程初探
Java的线程状态

- getState方法:返回该线程的状态,可能是NEW, RUNNABLE, BLOCKED, WAITING, TIME_WAITING, TEMINATED之一
- getName: 返回线程名称
- getPriority: 返回线程优先级
public class MyThread extends Thread{
@Override
public void run() {
System.out.println("线程状态:" + Thread.currentThread().getState());
System.out.println("线程名称:" + Thread.currentThread().getName());
System.out.println("线程优先级:" + Thread.currentThread().getPriority());
}
public static void main (String args []) {
MyThread t = new MyThread();
t.start();
}
}
输出:
线程状态:RUNNABLE
线程名称:Thread-0
线程优先级:5
线程的创建和启动
一. 继承Thread类创建线程
public class MyThread extends Thread {
private int i = 0;
public void run () {
i++;
System.out.println(i);
}
public static void main (String args []){
MyThread t = new MyThread();
t.start();
}
}
1
二. 实现Runnable接口创建线程
public class MyRunnable implements Runnable {
private int i =0;
@Override
public void run() {
i++;
System.out.println(i);
}
}
Test.java
public class Test {
public static void main (String args[]) {
Thread t = new Thread(new MyRunnable());
t.start();
}
}
输出
1
三. 通过Callable接口和Future接口创建线程
public interface Future<V> {
V get () throws ...; // 当任务完成时, 获取结果
V get (long timeout, TimeUnit unit); // 在get方法的基础上指定了超时时间
void cancel ( boolean mayInterupt); // 取消任务的执行
boolean isDone (); // 任务是否已完成
boolean isCancel (); // 任务是否已取消
}
- 对于Callable对象来说, Future对象可帮助它保存结果信息,当调用get方法的时候将会发生阻塞, 直到结果被返回。
- 而对于Runnable对象来说, 无需保存结果信息, 所以get方法一般为null, 这里Future的作用主要是可以调用cancel方法取消Runnable任务
FutureTask task = new FutureTask(new Callable);
得到的task既是一个Runnable也是一个Future。这样一来,可以先把得到的task传入Thread构造函数中创建线程并运行(作为Runnable使用), 接着通过task.get以阻塞的方式获得返回值(作为Future使用)
import java.util.concurrent.Callable;
public class MyCallable implements Callable {
@Override
public Object call() throws Exception {
Thread.sleep(1000);
return "返回值";
}
}
Test.java
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test {
public static void main (String args []) throws ExecutionException, InterruptedException {
// task同时实现了Runnable接口和Future接口
FutureTask task = new FutureTask(new MyCallable());
// 作为 Runnable 使用
Thread t = new Thread(task);
t.start();
// 作为Future使用, 调用get方法时将阻塞直到获得返回值
System.out.println(task.get());
}
}
返回值
四.通过线程池创建和管理线程
public interface Executor {
void execute(Runnable command);
}
public interface ExecutorService extends Executor {
void shutdown();
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
// 其他方法
}
- 调用submit方法可以将Runnable或Callable实例提交给线程池里的空闲线程执行,同时返回一个Future对象, 保存了和执行结果有关的信息
- 当线程池用完时, 需要调用 shutdown方法关闭线程
public class Executors {
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
}
}

public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i=0;i<3;i++) {
System.out.println("MyRunnable正在运行");
}
}
}
import java.util.concurrent.Callable;
public class MyCallable implements Callable{
@Override
public Object call() throws Exception {
for (int i=0;i<3;i++) {
System.out.println("MyCallable正在运行");
}
return "回调参数";
}
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test {
public static void main (String args []) throws ExecutionException, InterruptedException {
// 创建一个固定数量为2的线程池
ExecutorService service = Executors.newFixedThreadPool(2);
// 向线程池提交Callable任务,并将结果信息保存到Future中
Future callableFuture = service.submit(new MyCallable());
// 向线程池提交Runnable任务,并将结果信息保存到Future中
Future runnableFuture = service.submit(new MyRunnable());
// 输出结果信息
System.out.printf("MyCallable, 完成:%b取消:%b返回值:%s%n", callableFuture.isDone(),
callableFuture.isCancelled(), callableFuture.get());
System.out.printf("MyRunnable, 完成:%b取消:%b返回值:%s%n", runnableFuture.isDone(),
runnableFuture.isCancelled(), runnableFuture.get());
// 关闭线程池
service.shutdown();
}
}
MyCallable正在运行
MyCallable正在运行
MyCallable正在运行
MyCallable, 完成:true取消:false返回值:回调参数
MyRunnable正在运行
MyRunnable正在运行
MyRunnable正在运行
MyRunnable, 完成:false取消:false返回值:null
线程的运行
线程的阻塞(广义)
- 阻塞(Blocked)是试图获得对象锁(不是java.util.concurrent库中的锁),而对象锁暂时被其他线程持有导致
- 等待(Waiting)则是调用Object.wait,Thread.join或Lock.lock等方法导致的
- 计时等待(Time waiting)则是在等待的方法中引入了时间参数进入的状态,例如sleep(s)
线程的终止
1. 共享变量结束线程
public class InteruptSimulation implements Runnable{
private volatile static boolean stop = false;
@Override
public void run() {
try {
while (!stop) {
System.out.println("线程正在运行");
// 休眠5秒
Thread.sleep(5000);
}
System.out.println("线程终止");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main (String args []) throws InterruptedException {
Thread t = new Thread(new InteruptSimulation());
t.start();
// 休眠1秒
Thread.sleep(1000);
// 将共享变量stop置为true
System.out.println("发出终止线程的信号");
stop = true;
}
}
线程正在运行
发出终止线程的信号
// 约5s后输出
线程终止
2. 利用中断机制结束线程
public class InteruptReal implements Runnable{
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程正在运行");
Thread.sleep(5000);
}
} catch (InterruptedException e) {
// 发生中断异常后,中断状态位会被置为false,这里不做任何操作
}
System.out.println("线程已中断");
}
public static void main (String args []) throws InterruptedException {
Thread t = new Thread(new InteruptReal());
t.start();
// 休眠1s
Thread.sleep(1000);
System.out.println("发出终止线程的信号");
t.interrupt();
}
}
输出:
线程正在运行
发出终止线程的信号
// 立即输出
线程已中断
线程现在已经能够及时退出啦
public class InteruptReal implements Runnable{
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程正在运行");
Thread.sleep(5000);
}
} catch (InterruptedException e) {
System.out.println("中断状态位:"+Thread.currentThread().isInterrupted());
}
}
public static void main (String args []) throws InterruptedException {
Thread t = new Thread(new InteruptReal());
t.start();
// 休眠1s
Thread.sleep(1000);
System.out.println("发出中断");
t.interrupt();
}
}
输出:
线程正在运行
发出中断
中断状态位:false
线程的常用方法调用
Thread.sleep
Thread.yeild
Thread.join
public class JoinRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<3;i++) {
System.out.println(Thread.currentThread().getName()+ "正在执行");
}
}
public static void main (String args[]) throws InterruptedException {
Thread t = new Thread(new JoinRunnable());
t.start();
System.out.println("子线程执行完毕");
}
}
子线程执行完毕
Thread-0正在执行
Thread-0正在执行
Thread-0正在执行
public class JoinRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<3;i++) {
System.out.println(Thread.currentThread().getName()+ "正在执行");
}
}
public static void main (String args[]) throws InterruptedException {
Thread t = new Thread(new JoinRunnable());
t.start();
t.join();
System.out.println("子线程执行完毕");
}
}
输出:
Thread-0正在执行
Thread-0正在执行
Thread-0正在执行
子线程执行完毕
【Java】多线程初探的更多相关文章
- Java多线程初探
多线程 单线程的程序只有一个顺序执行流.多个顺序流之间互不干扰. 多线程的创建 定义Thread类的子类,重写该类的run()方法. 创建Thread子类的实例. 调用线程对象的start()方法来启 ...
- java并发初探ConcurrentHashMap
java并发初探ConcurrentHashMap Doug Lea在java并发上创造了不可磨灭的功劳,ConcurrentHashMap体现这位大师的非凡能力. 1.8中ConcurrentHas ...
- java并发初探ReentrantWriteReadLock
java并发初探ReentrantWriteReadLock ReenWriteReadLock类的优秀博客 ReentrantReadWriteLock读写锁详解 Java多线程系列--" ...
- 40个Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- Java多线程基础知识篇
这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程--让主线程等待子线程执行完毕
使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...
- Java多线程 2 线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
- java 多线程 1 线程 进程
Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报 分类: javaSE综合知识点(14) 版权声明:本文为博主原创文章,未经博 ...
随机推荐
- [国嵌笔记][028][Bootloader设计蓝图]
Bootloader的作用就是启动Linux内核 U-Boot简介 1.U-Boot是用于多种嵌入式CPU(ARM.x86.MIPS等)的bootloader程序,U-Boot不仅支持嵌入式Linux ...
- C#面试常见题目
1.CTS.CLS.CLR分别作何解释 CTS:Common Type System 通用系统类型.Int32.Int16→int.String→string.Boolean→bool CLS:Com ...
- java常量池詳解
一.相关概念 什么是常量用final修饰的成员变量表示常量,值一旦给定就无法改变!final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. Class文件中的常量池在Clas ...
- win10安装配置jdk的环境变量
换了个硬盘,用上了win10,发现win10安装好jdk之后,配置环境变量这个相对于win7和xp还是有那么一丢丢区别的,趁着夜色,随笔一记. 1.安装jdk之后,或者也可以用之前安装好的文件夹,先记 ...
- thinkphp无法加载控制器:Admin
在使用thinkphp时,通过某入口文件访问其他非默认的模块(比如Admin模块),出现报错: 无法加载控制器:Admin 原因:入口文件(比如index.php)中定义了绑定某个具体的模块 如:de ...
- 解决导入MySQL数据库提示"Unknown character set: 'utf8mb4'"错误
今天老左在准备迁移公司一个客户的网站到另外一台服务器中,根据正常的操作备份最新的网页文件和导出数据库,然后在新服务器中创建站点和数据库wget迁移进去解压.因为数据库比较小,所以直接用PHPMyAdm ...
- “此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态”的问题的解决
虚拟机使用的是VMware Workstation,并且首次在虚拟机体验64 位系统.在新建好虚拟机,运行时候就出现了VMware Workstation 的提醒:此主机支持 Intel VT-x,但 ...
- MySQL字符集设置—MySQL数据库乱码问题
MySQL(4.1以后版本) 服务器中有六个关键位置使用了字符集的概念,他们是:client .connection.database.results.server .system.MySQL有两个字 ...
- python_猜年龄
猜年龄,有三次机会,如何做? 1. 检查 输入的数据是否合法,通过异常try来处理,并记录 输入错误次数 2. 通过累加器,判断是否猜了3次,并提示还剩余多少的机会 3. 当3次错误,跳出 #!/us ...
- JavaScript数组的22种方法
原文:http://www.cnblogs.com/xiaohuochai/p/5682621.html javascript中数组的22种方法 前面的话 数组总共有22种方法,本文将其分为对象继 ...