Java 并发系列之一
Java 并发系列之一
简单的总结了一些 Java 常用的集合之后,发现许多集合都针对多线程提供了支持,比如 ConcurrentHashMap 使用分段锁来提高多线程环境下的性能表现与安全表现。所以我打算接着对 Java 并发的相关内容做一个简单总结。
线程与进程
进程是操作系统分配资源的基本单位,也就是说进程是运行中的程序。
线程是进程中的基本执行单元,每个进程都至少拥有一个线程。线程不独立拥有操作系统资源,线程共享进程的操作系统资源。
处理并发问题为什么使用多线程而不是多进程,在我看来主要有两点。一是进程间通信难度大于线程间通信,会增加开发难度,二是线程间切换效率高于进程间切换,选择多线程更适合并发场景。
线程的生命周期

这里我们只简单介绍线程 new->Runnable->Running->Dead 这个流程,不考虑 Block 的情况。
- 当我们创建一个 Thread 对象时,这个线程就进入了 new 的状态。
- 当时机成熟,我们调用这个对象的 start() 方法时,这个线程就进入了 Runnable 的状态。
- 然后这个线程就会等待 CPU 资源,如果获取到 CPU 资源就会自动运行。
- 运行结束后线程就会进入到 Dead 状态。
需要注意的是一个 Thread 对象只有一次调用 start() 方法的机会,无论这个线程是否顺利执行结束。
创建线程
创建线程也就是线程生命周期中的 new 状态。在 Java 中创建线程有 3 中方式:
- 继承 Thread 类并重写 run 方法
- 实现 Runnable 接口
- 实现 Callable 接口
继承 Thread 类来创建线程
使用继承 Thread 的方式可以直接在 run 方法中利用 this 来获取当前线程的信息,而不需要通过 Thread 类的静态方法 currentThread() 方法来获取当前的线程。
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(this.getName()+"正在运行");
}
}
public static void main(String[] args) {
Thread thread = new MyThread();
thread.start();
}
//输出结果:Thread-0 正在运行
如果想要快速实现一个匿名的类来执行某个简单操作的话,可以用下面的方式:
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
System.out.println(this.getName() + "正在执行");
}
}.start();
}
//输出结果:Thread-0 正在运行
实现 Runnable 接口来创建线程
由于 Java 是不支持多继承的,所以如果要继承 Thread 类以外的类,使用 Runnable 来实现或许是个不错的选择。
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在运行");
}
}
public static void main(String[] args) {
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
//输出结果:Thread-0 正在运行
其实 Runnable 接口只包含一个 run 方法,本质上还是通过重写 Thread 类的 run 方法来达到创建线程的目的。Runnable 还是一个函数式接口,所以想要声明一个匿名的 Thread 类还能通过下面的方式:
public static void main(String[] args) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "正在运行");
}).start();
}
//输出结果:Thread-0 正在运行
实现 Callable 接口来创建线程
上面两种创建线程的方式都是不支持返回值的,如果需要线程在执行之后提供返回值,就可以通过 Callable 来创建线程。使用 Callable 创建线程分为以下几个步骤:
- 创建类实现 Callable 接口的 call() 方法
- 使用 FutureTask 来包装上一步创建的类
- 使用 FutureTask 来创建 Thread 类
- 使用 FutureTask 对象的 get() 方法来获取返回值
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"正在运行");
return 316495132;
}
}
public static void main(String[] args)
throws ExecutionException,InterruptedException {
Callable callable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
System.out.println("返回值为:" + futureTask.get());
}
//输出结果:
//Thread-0 正在运行
//返回值为:316495132
小结
- 如果没有特殊的需求,实现 Runnable 接口或许是一个比较好的选择
- 如果需要线程执行完成后提供返回值,就只能选择继承 Callable 接口
Java 并发系列之一的更多相关文章
- Java并发系列[1]----AbstractQueuedSynchronizer源码分析之概要分析
学习Java并发编程不得不去了解一下java.util.concurrent这个包,这个包下面有许多我们经常用到的并发工具类,例如:ReentrantLock, CountDownLatch, Cyc ...
- Java并发系列[2]----AbstractQueuedSynchronizer源码分析之独占模式
在上一篇<Java并发系列[1]----AbstractQueuedSynchronizer源码分析之概要分析>中我们介绍了AbstractQueuedSynchronizer基本的一些概 ...
- Java并发系列[3]----AbstractQueuedSynchronizer源码分析之共享模式
通过上一篇的分析,我们知道了独占模式获取锁有三种方式,分别是不响应线程中断获取,响应线程中断获取,设置超时时间获取.在共享模式下获取锁的方式也是这三种,而且基本上都是大同小异,我们搞清楚了一种就能很快 ...
- Java并发系列[5]----ReentrantLock源码分析
在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...
- Java 并发系列之二:java 并发机制的底层实现原理
1. 处理器实现原子操作 2. volatile /** 补充: 主要作用:内存可见性,是变量在多个线程中可见,修饰变量,解决一写多读的问题. 轻量级的synchronized,不会造成阻塞.性能比s ...
- java并发系列 - 第28天:实战篇,微服务日志的伤痛,一并帮你解决掉
这是java高并发系列第28篇文章. 环境:jdk1.8. 本文内容 日志有什么用? 日志存在的痛点? 构建日志系统 日志有什么用? 系统出现故障的时候,可以通过日志信息快速定位问题,修复bug,恢复 ...
- java并发系列 - 第29天:高并发中常见的限流方式
这是java高并发系列第29篇. 环境:jdk1.8. 本文内容 介绍常见的限流算法 通过控制最大并发数来进行限流 通过漏桶算法来进行限流 通过令牌桶算法来进行限流 限流工具类RateLimiter ...
- Java 并发系列之八:java 并发工具(4个)
1. CountDownLatch 2. CyclicBarrier 3. Semaphore 4. Exchanger 5. txt java 并发工具 通俗理解 CountDownLatch 等A ...
- Java 并发系列之十:java 并发框架(2个)
1. Fork/Join框架 2. Executor框架 3. ThreadPoolExecutor 4. ScheduledThreadPoolExecutor 5. FutureTask 6. t ...
随机推荐
- 69)PHP,cookie的有效域
(1)默认情况下,cookie只在当前域下有效,比如我的loclhost/PHP或者shop.wang.com下有效. (2)其实一个域就代表一个网站, 以及域名就比如:www.baidu.com ...
- dbSNP|n SwissVar|n CanProVar|CHPP|mutation assessor|
癌症蛋白质基因组学主要研究driver性质的突变,该突变有可能是转化为癌基因的突变.抑癌基因突变.药物位点突变和蛋白突变,可以使用mutation assessor 预测突变 突变导致疾病,修饰仅影响 ...
- 疯狂收集个人信息的谷歌,为何不像Facebook那样让人毛骨悚然?
自从Facebook信息泄露丑闻事件发生后,互联网上的个人隐私及安全成为大众的"心病".而大众最讨厌的,是互联网企业收集自己的信息,因此都在积极讨伐这种行为.但他们却忘了,收集用户 ...
- mysql索引详细介绍
博客: https://blog.csdn.net/tongdanping/article/details/79878302#%E4%B8%89%E3%80%81%E7%B4%A2%E5%BC%95% ...
- Android开发之《异常处理》
Android NDK(七):JNI异常处理 Android NDK开发Crash错误定位 adb logcat | ndk-stack -sym /Users/yangxin/Documents/d ...
- 不疯“模”不成活,海尔阿里II代电视将极致进行到底
我去过很多现场,经历过很多新品发布,各种概念,各种颠覆,有点见怪不怪.这次受邀海尔阿里II代电视发布会,本也是带着一颗平常心. 2点30分发布会准时开场,当 "智慧模块"在讲解员手 ...
- MyBatis基本使用步骤
MyBatis是一个数据持久层(ORM)框架.把实体 类和SQL语句之间建立了映射关系,是一种半自 动化的ORM实现.MyBATIS需要开发人员自己来写sql语句,这可以增加了程序的灵活性,在一定程度 ...
- <USACO07JAN>解决问题Problem Solvingの思路
日常为dp贡献脑细胞 #include<iostream> #include<cmath> #include<cstdio> #include<cstdlib ...
- List、Set、数组之间的转换
数组转Collection 使用Apache Jakarta Commons Collections: import org.apache.commons.collections.Collection ...
- Python---7函数(调用&定义函数)
函数 Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs(),只有一个参数.可以直接从Python的官方网站查看文档: http: ...